Skip to content

Commit d48b241

Browse files
committed
feat: improve the type system
1 parent a55f35d commit d48b241

2 files changed

Lines changed: 24 additions & 11 deletions

File tree

fastapi_startkit/src/fastapi_startkit/masoniteorm/models/builder.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import inspect
2-
from typing import TYPE_CHECKING, Any
2+
from typing import TYPE_CHECKING, Any, Generic, TypeVar
33

44
from fastapi_startkit.masoniteorm.expressions.expressions import (
55
JoinClause,
@@ -19,9 +19,12 @@
1919

2020
if TYPE_CHECKING:
2121
from fastapi_startkit.masoniteorm.connections.connection import Connection
22+
from fastapi_startkit.masoniteorm.models.model import Model
2223

24+
TModel = TypeVar("TModel", bound="Model")
2325

24-
class QueryBuilder(EagerLoadMixin, SupportMixin):
26+
27+
class QueryBuilder(EagerLoadMixin, SupportMixin, Generic[TModel]):
2528
def __init__(self, connection: "Connection", grammar, processor):
2629
super().__init__()
2730
self.connection = connection
@@ -84,26 +87,31 @@ def limit(self, limit: int) -> "QueryBuilder":
8487
self._limit = limit
8588
return self
8689

87-
async def find(self, primary_key: str | int, columns=None):
90+
async def find(self, primary_key: str | int, columns=None) -> "TModel | None":
8891
return await self.where(self._model.__primary_key__, primary_key).first(columns)
8992

90-
async def find_or_fail(self, primary_key: str | int, columns=None):
93+
async def find_or_fail(self, primary_key: str | int, columns=None) -> "TModel":
94+
"""Return the record matching ``primary_key``.
95+
96+
Raises:
97+
ModelNotFoundException: If no record matches ``primary_key``.
98+
"""
9199
from fastapi_startkit.masoniteorm.exceptions import ModelNotFoundException
92100

93101
result = await self.find(primary_key, columns)
94102
if result is None:
95103
raise ModelNotFoundException(f"{type(self._model).__name__} with primary key {primary_key!r} not found.")
96104
return result
97105

98-
async def first_or_fail(self, columns=None):
106+
async def first_or_fail(self, columns=None) -> "TModel":
99107
from fastapi_startkit.masoniteorm.exceptions import ModelNotFoundException
100108

101109
result = await self.first(columns)
102110
if result is None:
103111
raise ModelNotFoundException(f"{type(self._model).__name__} not found.")
104112
return result
105113

106-
async def first(self, columns=None):
114+
async def first(self, columns=None) -> "TModel | None":
107115
if not columns:
108116
columns = []
109117

fastapi_startkit/src/fastapi_startkit/masoniteorm/models/model.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22
import inflection
33

4-
from typing import TYPE_CHECKING
4+
from typing import TYPE_CHECKING, Self
55

66
from fastapi_startkit.carbon import Carbon
77
from fastapi_startkit.masoniteorm.collection import Collection
@@ -92,7 +92,7 @@ def with_(cls, *eagers) -> "QueryBuilder":
9292
return cls.query().with_(*eagers)
9393

9494
@classmethod
95-
def where(cls, column, *args) -> "QueryBuilder":
95+
def where(cls, column, *args) -> "QueryBuilder[Self]":
9696
return cls.query().where(column, *args)
9797

9898
@classmethod
@@ -224,7 +224,12 @@ async def find(cls, primary_key: str | int, columns=None):
224224
return await cls.query().find(primary_key, columns)
225225

226226
@classmethod
227-
async def find_or_fail(cls, primary_key: str | int, columns=None):
227+
async def find_or_fail(cls, primary_key: str | int, columns=None) -> Self:
228+
"""Fetch the record matching ``primary_key``.
229+
230+
Raises:
231+
ModelNotFoundException: If no record matches ``primary_key``.
232+
"""
228233
return await cls.query().find_or_fail(primary_key, columns)
229234

230235
@classmethod
@@ -280,7 +285,7 @@ def new_model_instance(self, attributes=None, exists=False):
280285

281286
return model
282287

283-
def new_query(self) -> "QueryBuilder":
288+
def new_query(self) -> "QueryBuilder[Self]":
284289
return self.db_manager.connection(self.connection).query().set_model(self)
285290

286291
def hydrate(self, items):
@@ -310,7 +315,7 @@ def __getattr__(self, attribute):
310315
return self.get_attribute(attribute)
311316

312317
@classmethod
313-
def query(cls) -> "QueryBuilder":
318+
def query(cls) -> "QueryBuilder[Self]":
314319
return cls().new_query()
315320

316321
@classmethod

0 commit comments

Comments
 (0)