diff --git a/app/api/decks.py b/app/api/decks.py index 8110f6f..f2e53a6 100644 --- a/app/api/decks.py +++ b/app/api/decks.py @@ -2,7 +2,6 @@ import litestar from litestar.params import FromPath # noqa: TC002 -from litestar.plugins.pydantic import PydanticDTO from app import models, schemas from app.repositories import CardsRepository, DecksRepository # noqa: TC001 @@ -11,7 +10,7 @@ @litestar.get("/decks/") async def list_decks(decks_repository: DecksRepository) -> schemas.Decks: objects = await decks_repository.get_many() - return schemas.Decks(items=objects) # ty: ignore[invalid-argument-type] + return schemas.Decks.from_models(objects) @litestar.get("/decks/{deck_id:int}/") @@ -39,10 +38,10 @@ async def create_deck(data: schemas.DeckCreate, decks_repository: DecksRepositor @litestar.get("/decks/{deck_id:int}/cards/") async def list_cards(deck_id: FromPath[int], cards_repository: CardsRepository) -> schemas.Cards: objects = await cards_repository.list_for_deck(deck_id) - return schemas.Cards(items=objects) # ty: ignore[invalid-argument-type] + return schemas.Cards.from_models(objects) -@litestar.get("/cards/{card_id:int}/", return_dto=PydanticDTO[schemas.Card]) +@litestar.get("/cards/{card_id:int}/") async def get_card(card_id: FromPath[int], cards_repository: CardsRepository) -> schemas.Card: instance = await cards_repository.get_one(models.Card.id == card_id) return schemas.Card.model_validate(instance) @@ -53,7 +52,7 @@ async def create_cards( deck_id: FromPath[int], data: list[schemas.CardCreate], cards_repository: CardsRepository ) -> schemas.Cards: objects = await cards_repository.add_cards(deck_id, data) - return schemas.Cards(items=objects) # ty: ignore[invalid-argument-type] + return schemas.Cards.from_models(objects) @litestar.put("/decks/{deck_id:int}/cards/") @@ -61,7 +60,7 @@ async def update_cards( deck_id: FromPath[int], data: list[schemas.Card], cards_repository: CardsRepository ) -> schemas.Cards: objects = await cards_repository.upsert_cards(deck_id, data) - return schemas.Cards(items=objects) # ty: ignore[invalid-argument-type] + return schemas.Cards.from_models(objects) ROUTER: typing.Final = litestar.Router( diff --git a/app/schemas.py b/app/schemas.py index 84b82f6..a4b2d5a 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -1,11 +1,25 @@ +from typing import TYPE_CHECKING, Self + import pydantic from pydantic import BaseModel, PositiveInt +if TYPE_CHECKING: + from collections.abc import Iterable + + class Base(BaseModel): model_config = pydantic.ConfigDict(from_attributes=True) +class Collection[T: Base](Base): + items: list[T] + + @classmethod + def from_models(cls, objects: Iterable[object]) -> Self: + return cls.model_validate({"items": list(objects)}) + + class CardBase(Base): front: str back: str | None = None @@ -21,8 +35,8 @@ class Card(CardBase): deck_id: PositiveInt | None = None -class Cards(Base): - items: list[Card] +class Cards(Collection[Card]): + pass class DeckBase(Base): @@ -39,5 +53,5 @@ class Deck(DeckBase): cards: list[Card] | None -class Decks(Base): - items: list[Deck] +class Decks(Collection[Deck]): + pass