🐛 Fix Pydantic breaking changes

This commit is contained in:
Mawoka
2024-07-11 00:27:45 +02:00
parent b8aebd31ee
commit abafdd40f9
11 changed files with 91 additions and 89 deletions
+21 -21
View File
@@ -84,7 +84,7 @@ class UserSession(ormar.Model):
class ABCDQuizAnswer(BaseModel):
right: bool
answer: str
color: str | None
color: str | None = None
class RangeQuizAnswer(BaseModel):
@@ -97,7 +97,7 @@ class RangeQuizAnswer(BaseModel):
class VotingQuizAnswer(BaseModel):
answer: str
image: str | None = None
color: str | None
color: str | None = None
class QuizQuestionType(str, Enum):
@@ -145,10 +145,10 @@ class QuizInput(BaseModel):
public: bool = False
title: str
description: str
cover_image: str | None
background_color: str | None
cover_image: str | None = None
background_color: str | None = None
questions: list[QuizQuestion]
background_image: str | None
background_image: str | None = None
class Quiz(ormar.Model):
@@ -207,18 +207,18 @@ class PlayGame(BaseModel):
game_pin: str
started: bool = False
captcha_enabled: bool = False
cover_image: str | None
game_mode: str | None
cover_image: str | None = None
game_mode: str | None = None
current_question: int = -1
background_color: str | None
background_image: str | None
custom_field: str | None
background_color: str | None = None
background_image: str | None = None
custom_field: str | None = None
question_show: bool = False
class GamePlayer(BaseModel):
username: str
sid: str | None
sid: str | None = None
class GameAnswer2(BaseModel):
@@ -320,8 +320,8 @@ class OnlyId(BaseModel):
class PublicQuizTivityShare(BaseModel):
id: uuid.UUID
name: str | None
expire_in: int | None
name: str | None = None
expire_in: int | None = None
quiztivity: OnlyId
user: OnlyId
@@ -363,13 +363,13 @@ class PublicStorageItem(BaseModel):
id: uuid.UUID
uploaded_at: datetime
mime_type: str
hash: str | None
hash: str | None = None
size: int
deleted_at: datetime | None
alt_text: str | None
filename: str | None
thumbhash: str | None
server: str | None
deleted_at: datetime | None = None
alt_text: str | None = None
filename: str | None = None
thumbhash: str | None = None
server: str | None = None
imported: bool
@classmethod
@@ -425,8 +425,8 @@ class PrivateStorageItem(PublicStorageItem):
class UpdateStorageItem(BaseModel):
filename: str | None
alt_text: str | None
filename: str | None = None
alt_text: str | None = None
class Controller(ormar.Model):
+3 -3
View File
@@ -12,8 +12,8 @@ class Pdf(BaseModel):
class _MemoryCard(BaseModel):
image: str | None
text: str | None
image: str | None = None
text: str | None = None
id: str
@@ -53,6 +53,6 @@ TYPE_CLASS_LIST = {
class QuizTivityPage(BaseModel):
title: str | None
title: str | None = None
type: QuizTivityTypes
data: Pdf | Memory | Markdown | Abcd
+40 -40
View File
@@ -10,19 +10,19 @@ from pydantic import BaseModel
class _CoverMetadata(BaseModel):
id: UUID | None
resources: str | None
id: UUID | None = None
resources: str | None = None
class _CreatorAvatar(BaseModel):
url: str | None
id: UUID | None
type: str | None
bitmojiAvatarId: str | None
altText: str | None
contentType: str | None
width: int | None
height: int | None
url: str | None = None
id: UUID | None = None
type: str | None = None
bitmojiAvatarId: str | None = None
altText: str | None = None
contentType: str | None = None
width: int | None = None
height: int | None = None
class _LastEdit(BaseModel):
@@ -32,19 +32,19 @@ class _LastEdit(BaseModel):
class _ImageMetadata(BaseModel):
id: UUID | None
content_type: Optional[str]
width: Optional[int]
height: Optional[int]
resources: Optional[str]
id: UUID | None = None
content_type: Optional[str] = None
width: Optional[int] = None
height: Optional[int] = None
resources: Optional[str] = None
class _SampleQuestion(BaseModel):
image: str | None
imageMetadata: _ImageMetadata | None
image: str | None = None
imageMetadata: _ImageMetadata | None = None
title: str
type: str
time: int | None
time: int | None = None
class _Access(BaseModel):
@@ -57,19 +57,19 @@ class _Card(BaseModel):
title: str
description: str
slug: str
cover: str | None
coverMetadata: _CoverMetadata | dict[None, None] | None
cover: str | None = None
coverMetadata: _CoverMetadata | dict[None, None] | None = None
draftExists: bool
inventoryItemIds: List[Any]
inventoryItemIds: List[Any] = None
number_of_questions: int
creator: UUID
creator_username: str
creator_avatar: _CreatorAvatar | dict[None, None] | None
creator_avatar: _CreatorAvatar | dict[None, None] | None = None
badges: List[str]
visibility: int
locked: bool
writeProtection: bool
lastEdit: _LastEdit | None
lastEdit: _LastEdit | None = None
featured: bool
young_featured: bool
sponsored: bool
@@ -111,8 +111,8 @@ class _LanguageInfo(BaseModel):
class _Metadata(BaseModel):
access: _Access
duplicationProtection: bool | None
lastEdit: _LastEdit | None
duplicationProtection: bool | None = None
lastEdit: _LastEdit | None = None
class _Parent(BaseModel):
@@ -123,15 +123,15 @@ class _Parent(BaseModel):
class _Choice(BaseModel):
answer: str
correct: bool
languageInfo: _LanguageInfo | None
languageInfo: _LanguageInfo | None = None
class _Video(BaseModel):
startTime: float
endTime: float
service: str
full_url: Optional[str]
id: Optional[str]
full_url: Optional[str] = None
id: Optional[str] = None
class _Question(BaseModel):
@@ -141,12 +141,12 @@ class _Question(BaseModel):
points: bool
pointsMultiplier: int
choices: List[_Choice]
image: str | None
imageMetadata: _ImageMetadata | None
resources: Optional[str]
image: str | None = None
imageMetadata: _ImageMetadata | None = None
resources: Optional[str] = None
video: _Video
questionFormat: int
languageInfo: _LanguageInfo | None
languageInfo: _LanguageInfo | None = None
media: List[Any]
@@ -157,23 +157,23 @@ class _Kahoot(BaseModel):
creator_username: str
compatibilityLevel: int
creator_primary_usage: str
folderId: UUID | None
folderId: UUID | None = None
visibility: int
difficulty: int | None
difficulty: int | None = None
audience: str
audience: str
title: str
description: str
quizType: str
tags: str | None | List[str]
cover: str | None
coverMetadata: _CoverMetadata | dict[None, None] | None
tags: str | None | List[str] = None
cover: str | None = None
coverMetadata: _CoverMetadata | dict[None, None] | None = None
questions: List[_Question]
metadata: _Metadata
parent: _Parent | None
resources: str | None
parent: _Parent | None = None
resources: str | None = None
slug: str
languageInfo: _LanguageInfo | None
languageInfo: _LanguageInfo | None = None
inventoryItemIds: List[Any]
type: str
created: int
+2 -2
View File
@@ -15,12 +15,12 @@ from classquiz.kahoot_importer import _Entity
class _Response(BaseModel):
entities: List[_Entity]
totalHits: int
cursor: int | None
cursor: int | None = None
pageTimestamp: int
async def search(
query: str | None,
query: str | None = None,
limit: int | None = 9,
cursor: int | None = 1,
search_cluster: int | None = 1,
+1 -1
View File
@@ -18,7 +18,7 @@ router = APIRouter()
class SetControllerUpInput(BaseModel):
player_name: str | None
player_name: str | None = None
name: str
+2 -2
View File
@@ -50,7 +50,7 @@ class LoginSession(BaseModel):
user_id: str
step_1: set[StartLoginResponseTypes]
step_2: set[StartLoginResponseTypes]
webauthn_challenge: str | None
webauthn_challenge: str | None = None
step1_success: bool = False
@@ -58,7 +58,7 @@ class StartLoginResponse(BaseModel):
step_1: set[StartLoginResponseTypes]
step_2: set[StartLoginResponseTypes]
session_id: str
webauthn_data: None | str
webauthn_data: None | str = None
def verify_webauthn(data, fidocredentialss: list[FidoCredentials], login_session: LoginSession):
+1 -1
View File
@@ -47,7 +47,7 @@ async def get_newest_quizzes(
class SetModRatingForQuizInput(BaseModel):
rating: int | None
rating: int | None = None
@router.post("/rating/set/{quiz_id}")
+8 -6
View File
@@ -15,13 +15,14 @@ import ormar.exceptions
from classquiz.helpers import generate_spreadsheet, handle_import_from_excel
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File
from fastapi.responses import JSONResponse, StreamingResponse
from pydantic import ValidationError, BaseModel, Field
from pydantic import ValidationError, BaseModel
from classquiz.auth import get_current_user
from classquiz.config import redis, settings, storage, meilisearch
from classquiz.db.models import Quiz, User, PlayGame, GameInLobby, QuizQuestion, QuizQuestionType
from classquiz.helpers.box_controller import generate_code
from classquiz.kahoot_importer.import_quiz import import_quiz
from uuid import UUID
import urllib.parse
settings = settings()
@@ -54,9 +55,9 @@ class PublicQuizResponseUser(BaseModel):
id: uuid.UUID
class PublicQuizResponse(Quiz.get_pydantic()):
class PublicQuizResponse(Quiz.get_pydantic(exclude={"questions"})):
user_id: PublicQuizResponseUser
var_questions: list[QuizQuestion] = Field(..., alias="questions")
questions: list[QuizQuestion]
likes: int
dislikes: int
views: int
@@ -143,8 +144,8 @@ async def start_quiz(
class CheckIfCaptchaEnabledResponse(BaseModel):
enabled: bool
game_mode: str | None
custom_field: str | None
game_mode: str | None = None
custom_field: str | None = None
@router.get("/play/check_captcha/{game_pin}", response_model=CheckIfCaptchaEnabledResponse)
@@ -229,7 +230,8 @@ async def export_quiz_answers(export_token: str, game_pin: str):
data = json.loads(data)
data2 = await redis.get(f"game:{game_pin}")
game_data = PlayGame.parse_raw(data2)
quiz = await Quiz.objects.get_or_none(id=game_data.quiz_id)
print(type(game_data.quiz_id))
quiz = await Quiz.objects.get_or_none(id=UUID(game_data.quiz_id))
if quiz is None:
raise HTTPException(status_code=404, detail="quiz not found")
+4 -4
View File
@@ -25,9 +25,9 @@ async def get_shares(user: User = Depends(get_current_user)) -> list[PublicQuizT
class CreateShareInput(BaseModel):
name: str | None
name: str | None = None
quiztivity: UUID
expire_in: int | None
expire_in: int | None = None
@router.post("/")
@@ -55,8 +55,8 @@ async def delete_share(uuid: UUID, user: User = Depends(get_current_user)):
class UpdateShareInput(BaseModel):
name: str | None
expire_in: int | None
name: str | None = None
expire_in: int | None = None
@router.put("/{uuid}")
+1 -1
View File
@@ -297,7 +297,7 @@ async def get_other_avatar(respo: Response, user_id: uuid.UUID):
class InternalAuthData(BaseModel):
rememberme: str
jwt: str | None
jwt: str | None = None
@router.post("/auth/internal")
+8 -8
View File
@@ -61,10 +61,10 @@ def calculate_score(z: float, t: int) -> int:
async def set_answer(answers, game_pin: str, q_index: int, data: AnswerData) -> AnswerDataList:
if answers is None:
answers = AnswerDataList(__root__=[data])
answers = AnswerDataList([data])
else:
answers = AnswerDataList.parse_raw(answers)
answers.__root__.append(data)
answers.root.append(data)
await redis.set(
f"game_session:{game_pin}:{q_index}",
answers.json(),
@@ -76,8 +76,8 @@ async def set_answer(answers, game_pin: str, q_index: int, data: AnswerData) ->
class _JoinGameData(BaseModel):
username: str
game_pin: str
captcha: str | None
custom_field: str | None
captcha: str | None = None
custom_field: str | None = None
class _RejoinGameData(BaseModel):
@@ -280,7 +280,7 @@ async def get_question_results(sid: str, data: dict):
if redis_res is None:
redis_res = []
else:
redis_res = AnswerDataList.parse_raw(redis_res).dict()["__root__"]
redis_res = AnswerDataList.parse_raw(redis_res).model_dump()
game_data = PlayGame.parse_raw(await redis.get(f"game:{session['game_pin']}"))
game_data.question_show = False
await redis.set(f"game:{session['game_pin']}", game_data.json())
@@ -291,7 +291,7 @@ async def get_question_results(sid: str, data: dict):
class ABCDQuizAnswerWithoutSolution(BaseModel):
answer: str
color: str | None
color: str | None = None
class RangeQuizAnswerWithoutSolution(BaseModel):
@@ -360,7 +360,7 @@ class _SubmitAnswerDataOrderType(BaseModel):
class _SubmitAnswerData(BaseModel):
question_index: int
answer: str
complex_answer: list[_SubmitAnswerDataOrderType] | None
complex_answer: list[_SubmitAnswerDataOrderType] | None = None
@sio.event
@@ -448,7 +448,7 @@ async def submit_answer(sid: str, data: dict):
)
player_count = await redis.scard(f"game_session:{session['game_pin']}:players")
await sio.emit("player_answer", {})
if len(answers.__root__) == player_count:
if len(answers.root) == player_count:
# await sio.emit(
# "question_results",
# await redis.get(f"game_session:{session['game_pin']}:{data.question_index}"),