Improve typing
All checks were successful
Build Formula10 Docker Image / build-docker (push) Successful in 23s

This commit is contained in:
2024-02-20 13:45:16 +01:00
parent b6f7cd85cb
commit b1d05cf7c8
5 changed files with 97 additions and 99 deletions

View File

@ -1,10 +1,11 @@
import csv import csv
import os.path import os.path
from typing import List, Any
from model import * from flask_sqlalchemy import SQLAlchemy
from model import Team, Driver, Race, User, RaceResult, RaceGuess, TeamWinners, PodiumDrivers, SeasonGuess
def load_csv(filename): def load_csv(filename: str) -> List[List[str]]:
if not os.path.exists(filename): if not os.path.exists(filename):
print(f"Could not load data from file {filename}, as it doesn't exist!") print(f"Could not load data from file {filename}, as it doesn't exist!")
return [] return []
@ -15,7 +16,7 @@ def load_csv(filename):
return list(reader) return list(reader)
def write_csv(filename, objects): def write_csv(filename: str, objects: List[Any]):
if len(objects) == 0: if len(objects) == 0:
print(f"Could not write objects to file {filename}, as no objects were given!") print(f"Could not write objects to file {filename}, as no objects were given!")
return return
@ -28,15 +29,15 @@ def write_csv(filename, objects):
# Reload static database data, this has to be called from the app context # Reload static database data, this has to be called from the app context
def reload_static_data(db): def reload_static_data(db: SQLAlchemy):
print("Initializing Database with Static Values...") print("Initializing Database with Static Values...")
# Create it (if it doesn't exist!) # Create it (if it doesn't exist!)
db.create_all() db.create_all()
# Clear static data # Clear static data
Team.query.delete() db.session.query(Team).delete()
Driver.query.delete() db.session.query(Driver).delete()
Race.query.delete() db.session.query(Race).delete()
# Reload static data # Reload static data
for row in load_csv("static_data/teams.csv"): for row in load_csv("static_data/teams.csv"):
@ -49,18 +50,18 @@ def reload_static_data(db):
db.session.commit() db.session.commit()
def reload_dynamic_data(db): def reload_dynamic_data(db: SQLAlchemy):
print("Initializing Database with Dynamic Values...") print("Initializing Database with Dynamic Values...")
# Create it (if it doesn't exist!) # Create it (if it doesn't exist!)
db.create_all() db.create_all()
# Clear dynamic data # Clear dynamic data
User.query.delete() db.session.query(User).delete()
RaceResult.query.delete() db.session.query(RaceResult).delete()
RaceGuess.query.delete() db.session.query(RaceGuess).delete()
TeamWinners.query.delete() db.session.query(TeamWinners).delete()
PodiumDrivers.query.delete() db.session.query(PodiumDrivers).delete()
SeasonGuess.query.delete() db.session.query(SeasonGuess).delete()
# Reload dynamic data # Reload dynamic data
for row in load_csv("dynamic_data/users.csv"): for row in load_csv("dynamic_data/users.csv"):
@ -82,12 +83,12 @@ def reload_dynamic_data(db):
def export_dynamic_data(): def export_dynamic_data():
print("Exporting Userdata...") print("Exporting Userdata...")
users = User.query.all() users: List[User] = User.query.all()
raceresults = RaceResult.query.all() raceresults: List[RaceResult] = RaceResult.query.all()
raceguesses = RaceGuess.query.all() raceguesses: List[RaceGuess] = RaceGuess.query.all()
teamwinners = TeamWinners.query.all() teamwinners: List[TeamWinners] = TeamWinners.query.all()
podiumdrivers = PodiumDrivers.query.all() podiumdrivers: List[PodiumDrivers] = PodiumDrivers.query.all()
seasonguesses = SeasonGuess.query.all() seasonguesses: List[SeasonGuess] = SeasonGuess.query.all()
write_csv("dynamic_data/users.csv", users) write_csv("dynamic_data/users.csv", users)
write_csv("dynamic_data/raceresults.csv", raceresults) write_csv("dynamic_data/raceresults.csv", raceresults)

View File

@ -1,6 +1,6 @@
from urllib.parse import unquote from urllib.parse import unquote
from flask import Flask, render_template, request, redirect from flask import Flask, render_template, request, redirect
from werkzeug import Response
from model import * from model import *
from database_utils import reload_static_data, reload_dynamic_data, export_dynamic_data from database_utils import reload_static_data, reload_dynamic_data, export_dynamic_data
from template_model import TemplateModel from template_model import TemplateModel
@ -30,42 +30,42 @@ db.init_app(app)
@app.route("/") @app.route("/")
def root(): def root() -> Response:
return race_active_user("Everyone") return redirect("/race/Everyone")
@app.route("/save/all", strict_slashes=False) @app.route("/save/all")
def save(): def save() -> Response:
export_dynamic_data() export_dynamic_data()
return redirect("/") return redirect("/")
@app.route("/load/all") @app.route("/load/all")
def load(): def load() -> Response:
reload_static_data(db) reload_static_data(db)
reload_dynamic_data(db) reload_dynamic_data(db)
return redirect("/") return redirect("/")
@app.route("/load/static") @app.route("/load/static")
def load_static(): def load_static() -> Response:
reload_static_data(db) reload_static_data(db)
return redirect("/") return redirect("/")
@app.route("/load/dynamic") @app.route("/load/dynamic")
def load_dynamic(): def load_dynamic() -> Response:
reload_dynamic_data(db) reload_dynamic_data(db)
return redirect("/") return redirect("/")
@app.route("/race") @app.route("/race")
def race_root(): def race_root() -> Response:
return redirect("/race/Everyone") return redirect("/race/Everyone")
@app.route("/race/<user_name>") @app.route("/race/<user_name>")
def race_active_user(user_name: str): def race_active_user(user_name: str) -> str:
user_name = unquote(user_name) user_name = unquote(user_name)
model = TemplateModel() model = TemplateModel()
return render_template("race.jinja", return render_template("race.jinja",
@ -74,7 +74,7 @@ def race_active_user(user_name: str):
@app.route("/race-guess/<race_name>/<user_name>", methods=["POST"]) @app.route("/race-guess/<race_name>/<user_name>", methods=["POST"])
def race_guess_post(race_name: str, user_name: str): def race_guess_post(race_name: str, user_name: str) -> Response:
race_name = unquote(race_name) race_name = unquote(race_name)
user_name = unquote(user_name) user_name = unquote(user_name)
@ -88,7 +88,7 @@ def race_guess_post(race_name: str, user_name: str):
print("Error: Can't guess race result if the race result is already known!") print("Error: Can't guess race result if the race result is already known!")
return redirect(f"/race/{quote(user_name)}") return redirect(f"/race/{quote(user_name)}")
raceguess: RaceGuess | None = RaceGuess.query.filter_by(user_name=user_name, race_name=race_name).first() raceguess: RaceGuess | None = db.session.query(RaceGuess).filter_by(user_name=user_name, race_name=race_name).first()
if raceguess is None: if raceguess is None:
raceguess = RaceGuess() raceguess = RaceGuess()
@ -104,12 +104,12 @@ def race_guess_post(race_name: str, user_name: str):
@app.route("/season") @app.route("/season")
def season_root(): def season_root() -> Response:
return redirect("/season/Everyone") return redirect("/season/Everyone")
@app.route("/season/<user_name>") @app.route("/season/<user_name>")
def season_active_user(user_name: str): def season_active_user(user_name: str) -> str:
user_name = unquote(user_name) user_name = unquote(user_name)
model = TemplateModel() model = TemplateModel()
return render_template("season.jinja", return render_template("season.jinja",
@ -118,7 +118,7 @@ def season_active_user(user_name: str):
@app.route("/season-guess/<user_name>", methods=["POST"]) @app.route("/season-guess/<user_name>", methods=["POST"])
def season_guess_post(user_name: str): def season_guess_post(user_name: str) -> Response:
user_name = unquote(user_name) user_name = unquote(user_name)
guesses: List[str | None] = [ guesses: List[str | None] = [
request.form.get("hottakeselect"), request.form.get("hottakeselect"),
@ -129,7 +129,7 @@ def season_guess_post(user_name: str):
request.form.get("lostselect") request.form.get("lostselect")
] ]
teamwinnerguesses: List[str | None] = [ teamwinnerguesses: List[str | None] = [
request.form.get(f"teamwinner-{team.name}") for team in Team.query.all() request.form.get(f"teamwinner-{team.name}") for team in db.session.query(Team).all()
] ]
podiumdriverguesses: List[str] = request.form.getlist("podiumdrivers") podiumdriverguesses: List[str] = request.form.getlist("podiumdrivers")
@ -137,7 +137,7 @@ def season_guess_post(user_name: str):
print("Error: /guessseason could not obtain request data!") print("Error: /guessseason could not obtain request data!")
return redirect(f"/season/{quote(user_name)}") return redirect(f"/season/{quote(user_name)}")
seasonguess: SeasonGuess | None = SeasonGuess.query.filter_by(user_name=user_name).first() seasonguess: SeasonGuess | None = db.session.query(SeasonGuess).filter_by(user_name=user_name).first()
teamwinners: TeamWinners | None = seasonguess.team_winners if seasonguess is not None else None teamwinners: TeamWinners | None = seasonguess.team_winners if seasonguess is not None else None
podiumdrivers: PodiumDrivers | None = seasonguess.podium_drivers if seasonguess is not None else None podiumdrivers: PodiumDrivers | None = seasonguess.podium_drivers if seasonguess is not None else None
@ -176,12 +176,12 @@ def season_guess_post(user_name: str):
@app.route("/result") @app.route("/result")
def result_root(): def result_root() -> Response:
return redirect("/result/Current") return redirect("/result/Current")
@app.route("/result/<race_name>") @app.route("/result/<race_name>")
def result_active_race(race_name: str): def result_active_race(race_name: str) -> str:
race_name = unquote(race_name) race_name = unquote(race_name)
model = TemplateModel() model = TemplateModel()
return render_template("enter.jinja", return render_template("enter.jinja",
@ -190,7 +190,7 @@ def result_active_race(race_name: str):
@app.route("/result-enter/<result_race_name>", methods=["POST"]) @app.route("/result-enter/<result_race_name>", methods=["POST"])
def result_enter_post(result_race_name: str): def result_enter_post(result_race_name: str) -> Response:
result_race_name = unquote(result_race_name) result_race_name = unquote(result_race_name)
pxxs: List[str] = request.form.getlist("pxxdrivers") pxxs: List[str] = request.form.getlist("pxxdrivers")
dnfs: List[str] = request.form.getlist("dnf-drivers") dnfs: List[str] = request.form.getlist("dnf-drivers")
@ -200,7 +200,7 @@ def result_enter_post(result_race_name: str):
pxxs_dict: Dict[str, str] = {str(position + 1): driver for position, driver in enumerate(pxxs)} pxxs_dict: Dict[str, str] = {str(position + 1): driver for position, driver in enumerate(pxxs)}
dnfs_dict: Dict[str, str] = {str(position + 1): driver for position, driver in enumerate(pxxs) if driver in dnfs} dnfs_dict: Dict[str, str] = {str(position + 1): driver for position, driver in enumerate(pxxs) if driver in dnfs}
raceresult: RaceResult | None = RaceResult.query.filter_by(race_name=result_race_name).first() raceresult: RaceResult | None = db.session.query(RaceResult).filter_by(race_name=result_race_name).first()
if raceresult is None: if raceresult is None:
raceresult = RaceResult() raceresult = RaceResult()
@ -212,7 +212,7 @@ def result_enter_post(result_race_name: str):
raceresult.excluded_driver_names = excludes raceresult.excluded_driver_names = excludes
db.session.commit() db.session.commit()
race: Race | None = Race.query.filter_by(name=result_race_name).first() race: Race | None = db.session.query(Race).filter_by(name=result_race_name).first()
if race is None: if race is None:
print("Error: Can't redirect to /enter/<GrandPrix> because race couldn't be found") print("Error: Can't redirect to /enter/<GrandPrix> because race couldn't be found")
return redirect(f"/result/Current") return redirect(f"/result/Current")
@ -221,7 +221,7 @@ def result_enter_post(result_race_name: str):
@app.route("/user") @app.route("/user")
def user_root(): def user_root() -> str:
users: List[User] = User.query.all() users: List[User] = User.query.all()
return render_template("users.jinja", return render_template("users.jinja",
@ -229,14 +229,14 @@ def user_root():
@app.route("/user-add", methods=["POST"]) @app.route("/user-add", methods=["POST"])
def user_add_post(): def user_add_post() -> Response:
username: str | None = request.form.get("select-add-user") username: str | None = request.form.get("select-add-user")
if username is None or len(username) == 0: if username is None or len(username) == 0:
print(f"Not adding user, since no username was received") print(f"Not adding user, since no username was received")
return user_root() return redirect("/user")
if len(User.query.filter_by(name=username).all()) > 0: if len(db.session.query(User).filter_by(name=username).all()) > 0:
print(f"Not adding user {username}: Already exists!") print(f"Not adding user {username}: Already exists!")
return redirect("/user") return redirect("/user")
@ -249,7 +249,7 @@ def user_add_post():
@app.route("/user-delete", methods=["POST"]) @app.route("/user-delete", methods=["POST"])
def user_delete_post(): def user_delete_post() -> Response:
username = request.form.get("select-delete-user") username = request.form.get("select-delete-user")
if username is None or len(username) == 0: if username is None or len(username) == 0:

View File

@ -1,13 +1,12 @@
import json import json
from datetime import datetime from datetime import datetime
from typing import List, Dict from typing import Any, List, Dict
from urllib.parse import quote from urllib.parse import quote
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Integer, String, DateTime, ForeignKey from sqlalchemy import Integer, String, DateTime, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
db = SQLAlchemy() db: SQLAlchemy = SQLAlchemy()
#################################### ####################################
# Static Data (Defined in Backend) # # Static Data (Defined in Backend) #
@ -21,7 +20,7 @@ class Race(db.Model):
""" """
__tablename__ = "race" __tablename__ = "race"
def from_csv(self, row): def from_csv(self, row: List[str]):
self.name = str(row[0]) self.name = str(row[0])
self.number = int(row[1]) self.number = int(row[1])
self.date = datetime.strptime(row[2], "%Y-%m-%d") self.date = datetime.strptime(row[2], "%Y-%m-%d")
@ -44,7 +43,7 @@ class Team(db.Model):
""" """
__tablename__ = "team" __tablename__ = "team"
def from_csv(self, row): def from_csv(self, row: List[str]):
self.name = str(row[0]) self.name = str(row[0])
return self return self
@ -58,7 +57,7 @@ class Driver(db.Model):
""" """
__tablename__ = "driver" __tablename__ = "driver"
def from_csv(self, row): def from_csv(self, row: List[str]):
self.name = str(row[0]) self.name = str(row[0])
self.abbr = str(row[1]) self.abbr = str(row[1])
self.team_name = str(row[2]) self.team_name = str(row[2])
@ -86,11 +85,11 @@ class User(db.Model):
__tablename__ = "user" __tablename__ = "user"
__csv_header__ = ["name"] __csv_header__ = ["name"]
def from_csv(self, row): def from_csv(self, row: List[str]):
self.name = str(row[0]) self.name = str(row[0])
return self return self
def to_csv(self): def to_csv(self) -> List[Any]:
return [ return [
self.name self.name
] ]
@ -111,14 +110,14 @@ class RaceResult(db.Model):
__allow_unmapped__ = True # TODO: Used for json conversion, move this to some other class instead __allow_unmapped__ = True # TODO: Used for json conversion, move this to some other class instead
__csv_header__ = ["race_name", "pxx_driver_names_json", "dnf_driver_names_json", "excluded_driver_names_json"] __csv_header__ = ["race_name", "pxx_driver_names_json", "dnf_driver_names_json", "excluded_driver_names_json"]
def from_csv(self, row): def from_csv(self, row: List[str]):
self.race_name = str(row[0]) self.race_name = str(row[0])
self.pxx_driver_names_json = str(row[1]) self.pxx_driver_names_json = str(row[1])
self.dnf_driver_names_json = str(row[2]) self.dnf_driver_names_json = str(row[2])
self.excluded_driver_names_json = str(row[3]) self.excluded_driver_names_json = str(row[3])
return self return self
def to_csv(self): def to_csv(self) -> List[Any]:
return [ return [
self.race_name, self.race_name,
self.pxx_driver_names_json, self.pxx_driver_names_json,
@ -166,7 +165,7 @@ class RaceResult(db.Model):
if self._pxx_drivers is None: if self._pxx_drivers is None:
self._pxx_drivers = dict() self._pxx_drivers = dict()
for position, driver_name in self.pxx_driver_names.items(): for position, driver_name in self.pxx_driver_names.items():
driver = Driver.query.filter_by(name=driver_name).first() driver: Driver | None = db.session.query(Driver).filter_by(name=driver_name).first()
if driver is None: if driver is None:
raise Exception(f"Error: Couldn't find driver with id {driver_name}") raise Exception(f"Error: Couldn't find driver with id {driver_name}")
@ -176,11 +175,11 @@ class RaceResult(db.Model):
@property @property
def pxx_drivers_values(self) -> List[Driver]: def pxx_drivers_values(self) -> List[Driver]:
drivers: List[Driver] = [] drivers: List[Driver] = list()
# I don't know what order dict.values() etc. will return... # I don't know what order dict.values() etc. will return...
for position in range(1, 21): for position in range(1, 21):
drivers += [self.pxx_drivers[str(position)]] drivers.append(self.pxx_drivers[str(position)])
return drivers return drivers
@ -189,7 +188,7 @@ class RaceResult(db.Model):
if self._dnf_drivers is None: if self._dnf_drivers is None:
self._dnf_drivers = dict() self._dnf_drivers = dict()
for position, driver_name in self.dnf_driver_names.items(): for position, driver_name in self.dnf_driver_names.items():
driver = Driver.query.filter_by(name=driver_name).first() driver: Driver | None = db.session.query(Driver).filter_by(name=driver_name).first()
if driver is None: if driver is None:
raise Exception(f"Error: Couldn't find driver with id {driver_name}") raise Exception(f"Error: Couldn't find driver with id {driver_name}")
@ -200,13 +199,13 @@ class RaceResult(db.Model):
@property @property
def excluded_drivers(self) -> List[Driver]: def excluded_drivers(self) -> List[Driver]:
if self._excluded_drivers is None: if self._excluded_drivers is None:
self._excluded_drivers = [] self._excluded_drivers = list()
for driver_name in self.excluded_driver_names: for driver_name in self.excluded_driver_names:
driver = Driver.query.filter_by(name=driver_name).first() driver: Driver | None = db.session.query(Driver).filter_by(name=driver_name).first()
if driver is None: if driver is None:
raise Exception(f"Error: Couldn't find driver with id {driver_name}") raise Exception(f"Error: Couldn't find driver with id {driver_name}")
self._excluded_drivers += [driver] self._excluded_drivers.append(driver)
return self._excluded_drivers return self._excluded_drivers
@ -230,14 +229,14 @@ class RaceGuess(db.Model):
__tablename__ = "raceguess" __tablename__ = "raceguess"
__csv_header__ = ["user_name", "race_name", "pxx_driver_name", "dnf_driver_name"] __csv_header__ = ["user_name", "race_name", "pxx_driver_name", "dnf_driver_name"]
def from_csv(self, row): def from_csv(self, row: List[str]):
self.user_name = str(row[0]) self.user_name = str(row[0])
self.race_name = str(row[1]) self.race_name = str(row[1])
self.pxx_driver_name = str(row[2]) self.pxx_driver_name = str(row[2])
self.dnf_driver_name = str(row[3]) self.dnf_driver_name = str(row[3])
return self return self
def to_csv(self): def to_csv(self) -> List[Any]:
return [ return [
self.user_name, self.user_name,
self.race_name, self.race_name,
@ -265,12 +264,12 @@ class TeamWinners(db.Model):
__allow_unmapped__ = True __allow_unmapped__ = True
__csv_header__ = ["user_name", "teamwinner_driver_names_json"] __csv_header__ = ["user_name", "teamwinner_driver_names_json"]
def from_csv(self, row): def from_csv(self, row: List[str]):
self.user_name = str(row[0]) self.user_name = str(row[0])
self.teamwinner_driver_names_json = str(row[1]) self.teamwinner_driver_names_json = str(row[1])
return self return self
def to_csv(self): def to_csv(self) -> List[Any]:
return [ return [
self.user_name, self.user_name,
self.teamwinner_driver_names_json self.teamwinner_driver_names_json
@ -294,13 +293,13 @@ class TeamWinners(db.Model):
@property @property
def teamwinners(self) -> List[Driver]: def teamwinners(self) -> List[Driver]:
if self._teamwinner_drivers is None: if self._teamwinner_drivers is None:
self._teamwinner_drivers = [] self._teamwinner_drivers = list()
for driver_name in self.teamwinner_driver_names: for driver_name in self.teamwinner_driver_names:
driver = Driver.query.filter_by(name=driver_name).first() driver: Driver | None = db.session.query(Driver).filter_by(name=driver_name).first()
if driver is None: if driver is None:
raise Exception(f"Error: Couldn't find driver with id {driver_name}") raise Exception(f"Error: Couldn't find driver with id {driver_name}")
self._teamwinner_drivers += [driver] self._teamwinner_drivers.append(driver)
return self._teamwinner_drivers return self._teamwinner_drivers
@ -313,12 +312,12 @@ class PodiumDrivers(db.Model):
__allow_unmapped__ = True __allow_unmapped__ = True
__csv_header__ = ["user_name", "podium_driver_names_json"] __csv_header__ = ["user_name", "podium_driver_names_json"]
def from_csv(self, row): def from_csv(self, row: List[str]):
self.user_name = str(row[0]) self.user_name = str(row[0])
self.podium_driver_names_json = str(row[1]) self.podium_driver_names_json = str(row[1])
return self return self
def to_csv(self): def to_csv(self) -> List[Any]:
return [ return [
self.user_name, self.user_name,
self.podium_driver_names_json self.podium_driver_names_json
@ -342,13 +341,13 @@ class PodiumDrivers(db.Model):
@property @property
def podium_drivers(self) -> List[Driver]: def podium_drivers(self) -> List[Driver]:
if self._podium_drivers is None: if self._podium_drivers is None:
self._podium_drivers = [] self._podium_drivers = list()
for driver_name in self.podium_driver_names: for driver_name in self.podium_driver_names:
driver = Driver.query.filter_by(name=driver_name).first() driver: Driver | None = db.session.query(Driver).filter_by(name=driver_name).first()
if driver is None: if driver is None:
raise Exception(f"Error: Couldn't find driver with id {driver_name}") raise Exception(f"Error: Couldn't find driver with id {driver_name}")
self._podium_drivers += [driver] self._podium_drivers.append(driver)
return self._podium_drivers return self._podium_drivers
@ -362,7 +361,7 @@ class SeasonGuess(db.Model):
"overtake_driver_name", "dnf_driver_name", "gained_driver_name", "lost_driver_name", "overtake_driver_name", "dnf_driver_name", "gained_driver_name", "lost_driver_name",
"team_winners_id", "podium_drivers_id"] "team_winners_id", "podium_drivers_id"]
def from_csv(self, row): def from_csv(self, row: List[str]):
self.user_name = str(row[0]) # Also used as foreign key for teamwinners + podiumdrivers self.user_name = str(row[0]) # Also used as foreign key for teamwinners + podiumdrivers
self.hot_take = str(row[1]) self.hot_take = str(row[1])
self.p2_team_name = str(row[2]) self.p2_team_name = str(row[2])
@ -374,7 +373,7 @@ class SeasonGuess(db.Model):
self.podium_drivers_id = str(row[8]) self.podium_drivers_id = str(row[8])
return self return self
def to_csv(self): def to_csv(self) -> List[Any]:
return [ return [
self.user_name, self.user_name,
self.hot_take, self.hot_take,

View File

@ -1,8 +1,6 @@
from typing import List, Iterable, Callable, TypeVar, Dict, overload, Any from typing import List, Iterable, Callable, TypeVar, Dict, overload
from sqlalchemy import desc from sqlalchemy import desc
from model import User, RaceResult, RaceGuess, Race, Driver, Team, SeasonGuess, db
from model import User, RaceResult, RaceGuess, Race, Driver, Team, SeasonGuess
_T = TypeVar("_T") _T = TypeVar("_T")
@ -73,7 +71,7 @@ class TemplateModel:
Returns a list of all users in the database. Returns a list of all users in the database.
""" """
if self._all_users is None: if self._all_users is None:
self._all_users = User.query.all() self._all_users = db.session.query(User).all()
return self._all_users return self._all_users
@ -106,7 +104,7 @@ class TemplateModel:
Returns a list of all race results in the database, in descending order (most recent first). Returns a list of all race results in the database, in descending order (most recent first).
""" """
if self._all_race_results is None: if self._all_race_results is None:
self._all_race_results = RaceResult.query.join(RaceResult.race).order_by(desc(Race.number)).all() self._all_race_results = db.session.query(RaceResult).join(RaceResult.race).order_by(desc(Race.number)).all()
return self._all_race_results return self._all_race_results
@ -122,26 +120,26 @@ class TemplateModel:
Returns a list of all race guesses in the database. Returns a list of all race guesses in the database.
""" """
if self._all_race_guesses is None: if self._all_race_guesses is None:
self._all_race_guesses = RaceGuess.query.all() self._all_race_guesses = db.session.query(RaceGuess).all()
return self._all_race_guesses return self._all_race_guesses
@overload @overload
def race_guesses_by(self, *, user_name) -> List[RaceGuess]: def race_guesses_by(self, *, user_name: str) -> List[RaceGuess]:
""" """
Returns a list of all race guesses made by a specific user. Returns a list of all race guesses made by a specific user.
""" """
return self.race_guesses_by(user_name=user_name) return self.race_guesses_by(user_name=user_name)
@overload @overload
def race_guesses_by(self, *, race_name) -> List[RaceGuess]: def race_guesses_by(self, *, race_name: str) -> List[RaceGuess]:
""" """
Returns a list of all race guesses made for a specific race. Returns a list of all race guesses made for a specific race.
""" """
return self.race_guesses_by(race_name=race_name) return self.race_guesses_by(race_name=race_name)
@overload @overload
def race_guesses_by(self, *, user_name, race_name) -> RaceGuess | None: def race_guesses_by(self, *, user_name: str, race_name: str) -> RaceGuess | None:
""" """
Returns a single race guess by a specific user for a specific race, or None, if this guess doesn't exist. Returns a single race guess by a specific user for a specific race, or None, if this guess doesn't exist.
""" """
@ -154,7 +152,7 @@ class TemplateModel:
""" """
return self.race_guesses_by() return self.race_guesses_by()
def race_guesses_by(self, *, user_name=None, race_name=None) -> RaceGuess | List[RaceGuess] | Dict[str, Dict[str, RaceGuess]] | None: def race_guesses_by(self, *, user_name: str | None = None, race_name: str | None = None) -> RaceGuess | List[RaceGuess] | Dict[str, Dict[str, RaceGuess]] | None:
# List of all guesses by a single user # List of all guesses by a single user
if user_name is not None and race_name is None: if user_name is not None and race_name is None:
predicate: Callable[[RaceGuess], bool] = lambda guess: guess.user_name == user_name predicate: Callable[[RaceGuess], bool] = lambda guess: guess.user_name == user_name
@ -187,12 +185,12 @@ class TemplateModel:
def all_season_guesses(self) -> List[SeasonGuess]: def all_season_guesses(self) -> List[SeasonGuess]:
if self._all_season_guesses is None: if self._all_season_guesses is None:
self._all_season_guesses = SeasonGuess.query.all() self._all_season_guesses = db.session.query(SeasonGuess).all()
return self._all_season_guesses return self._all_season_guesses
@overload @overload
def season_guesses_by(self, *, user_name) -> SeasonGuess: def season_guesses_by(self, *, user_name: str) -> SeasonGuess:
""" """
Returns the season guess made by a specific user. Returns the season guess made by a specific user.
""" """
@ -205,7 +203,7 @@ class TemplateModel:
""" """
return self.season_guesses_by() return self.season_guesses_by()
def season_guesses_by(self, *, user_name=None) -> SeasonGuess | Dict[str, SeasonGuess] | None: def season_guesses_by(self, *, user_name: str | None = None) -> SeasonGuess | Dict[str, SeasonGuess] | None:
if user_name is not None: if user_name is not None:
predicate: Callable[[SeasonGuess], bool] = lambda guess: guess.user_name == user_name predicate: Callable[[SeasonGuess], bool] = lambda guess: guess.user_name == user_name
return find_single_or_none(predicate, self.all_season_guesses()) return find_single_or_none(predicate, self.all_season_guesses())
@ -226,7 +224,7 @@ class TemplateModel:
Returns a list of all races in the database. Returns a list of all races in the database.
""" """
if self._all_races is None: if self._all_races is None:
self._all_races = Race.query.order_by(desc(Race.number)).all() self._all_races = db.session.query(Race).order_by(desc(Race.number)).all()
return self._all_races return self._all_races
@ -248,7 +246,7 @@ class TemplateModel:
Returns a list of all teams in the database. Returns a list of all teams in the database.
""" """
if self._all_teams is None: if self._all_teams is None:
self._all_teams = Team.query.all() self._all_teams = db.session.query(Team).all()
return self._all_teams return self._all_teams
@ -257,7 +255,7 @@ class TemplateModel:
Returns a list of all drivers in the database, including the NONE driver. Returns a list of all drivers in the database, including the NONE driver.
""" """
if self._all_drivers is None: if self._all_drivers is None:
self._all_drivers = Driver.query.all() self._all_drivers = db.session.query(Driver).all()
return self._all_drivers return self._all_drivers
@ -269,7 +267,7 @@ class TemplateModel:
return find_multiple(predicate, self.all_drivers()) return find_multiple(predicate, self.all_drivers())
@overload @overload
def drivers_by(self, *, team_name) -> List[Driver]: def drivers_by(self, *, team_name: str) -> List[Driver]:
""" """
Returns a list of all drivers driving for a certain team. Returns a list of all drivers driving for a certain team.
""" """
@ -282,7 +280,7 @@ class TemplateModel:
""" """
return self.drivers_by() return self.drivers_by()
def drivers_by(self, *, team_name=None) -> List[Driver] | Dict[str, List[Driver]]: def drivers_by(self, *, team_name: str | None = None) -> List[Driver] | Dict[str, List[Driver]]:
if team_name is not None: if team_name is not None:
predicate: Callable[[Driver], bool] = lambda driver: driver.team.name == team_name predicate: Callable[[Driver], bool] = lambda driver: driver.team.name == team_name
return find_multiple(predicate, self.all_drivers_except_none(), 2) return find_multiple(predicate, self.all_drivers_except_none(), 2)

View File

@ -146,7 +146,7 @@ P{{ result.race.pxx + 3 }}: {{ result.pxx(3).abbr }}
<body> <body>
<nav class="navbar fixed-top navbar-expand-lg bg-body-tertiary"> <nav class="navbar fixed-top navbar-expand-lg bg-body-tertiary shadow-sm">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="/race"> <a class="navbar-brand" href="/race">
<img src="../static/image/f1_logo.svg" alt="Logo" width="120" height="30" <img src="../static/image/f1_logo.svg" alt="Logo" width="120" height="30"