55from typing import TYPE_CHECKING , Any , Final , Literal , NamedTuple , Self
66from uuid import UUID , uuid4
77
8- from asyncpg .exceptions import ForeignKeyViolationError , UniqueViolationError
98from sqlalchemy import UUID as COLUMN_UUID
109from sqlalchemy import Column , DateTime , Row , Select , select
11- from sqlalchemy .exc import IntegrityError , NoResultFound
10+ from sqlalchemy .exc import NoResultFound
1211from sqlalchemy .ext .asyncio .session import AsyncSession
1312from sqlalchemy .inspection import Inspectable
1413from sqlalchemy .orm import DeclarativeBaseNoMeta as _DeclarativeBaseNoMeta
2120from sqlalchemy .sql .elements import BinaryExpression , ColumnElement , SQLCoreOperations , UnaryExpression
2221from sqlalchemy .sql .roles import ColumnsClauseRole , TypedColumnsClauseRole
2322
24- from futuramaapi .helpers .pydantic import BaseModel
25-
2623if TYPE_CHECKING :
2724 from sqlalchemy .engine .result import Result
2825
@@ -37,15 +34,6 @@ class ModelBaseError(Exception): ...
3734class ModelDoesNotExistError (ModelBaseError ): ...
3835
3936
40- class ModelAlreadyExistsError (ModelBaseError ): ...
41-
42-
43- class ModelForeignKeyViolationError (ModelBaseError ): ...
44-
45-
46- class ModelFieldError (ModelBaseError ): ...
47-
48-
4937class FilterStatementKwargs (NamedTuple ):
5038 offset : int | None = None
5139 limit : int | None = None
@@ -159,19 +147,6 @@ async def get(
159147 except NoResultFound as err :
160148 raise ModelDoesNotExistError () from err
161149
162- @classmethod
163- async def get_or_none (
164- cls ,
165- session : AsyncSession ,
166- val : int | str | UUID ,
167- / ,
168- field : InstrumentedAttribute | None = None ,
169- ) -> Self | None :
170- try :
171- return await cls .get (session , val , field = field )
172- except ModelDoesNotExistError :
173- return None
174-
175150 @classmethod
176151 def get_order_by (
177152 cls ,
@@ -225,87 +200,6 @@ def get_binary_cond(cls, field: Column[str | Enum], value: str, /) -> BinaryExpr
225200
226201 return field == value
227202
228- @classmethod
229- async def create (
230- cls ,
231- session : AsyncSession ,
232- data : BaseModel ,
233- / ,
234- * ,
235- commit : bool = True ,
236- extra_fields : dict [
237- str ,
238- Any ,
239- ]
240- | None = None ,
241- ) -> Self :
242- obj : Self = cls (** data .to_dict (by_alias = False , reveal_secrets = True ))
243- if extra_fields is not None :
244- for name , value in extra_fields .items ():
245- setattr (obj , name , value )
246- session .add (obj )
247- if commit is True :
248- try :
249- await session .commit ()
250- except IntegrityError as err :
251- await session .rollback ()
252-
253- if err .orig .sqlstate == UniqueViolationError .sqlstate :
254- raise ModelAlreadyExistsError () from None
255- elif err .orig .sqlstate == ForeignKeyViolationError .sqlstate :
256- raise ModelForeignKeyViolationError () from None
257- raise
258- return obj
259-
260- @classmethod
261- def validate_field (cls , field : str , value : Any , / ) -> None :
262- try :
263- field_ : InstrumentedAttribute = getattr (cls , field )
264- except AttributeError as err :
265- logger .exception (
266- "Field does not exist." ,
267- extra = {
268- "data" : {
269- "field" : field ,
270- "err" : err ,
271- "model" : cls ,
272- }
273- },
274- )
275- raise ModelFieldError () from None
276- if field_ .nullable is False and value is None :
277- logger .exception (
278- "Attempt to assign None to non nullable field." ,
279- extra = {
280- "data" : {
281- "field" : field ,
282- "model" : cls ,
283- }
284- },
285- )
286- raise ModelFieldError () from None
287-
288- @classmethod
289- async def update (
290- cls ,
291- session : AsyncSession ,
292- id_ : int ,
293- data : dict ,
294- / ,
295- ) -> Self :
296- try :
297- obj : Self = await cls .get (session , id_ )
298- except ModelDoesNotExistError :
299- raise
300-
301- for field , value in data .items ():
302- if value is not None :
303- setattr (obj , field , value )
304-
305- await session .commit ()
306-
307- return obj
308-
309203 @classmethod
310204 async def filter (
311205 cls ,
@@ -316,23 +210,3 @@ async def filter(
316210 statement = cls .get_filter_statement (kwargs )
317211 cursor : Result = await session .execute (statement )
318212 return cursor .scalars ().all ()
319-
320- @classmethod
321- async def get_random (
322- cls ,
323- session : AsyncSession ,
324- / ,
325- * ,
326- extra_where : list [ColumnElement [bool ]] | None = None ,
327- ) -> Self :
328- # TODO: Implement extra where
329- options : list [Load ] = cls .get_options ()
330- statement : Select [tuple [Base ]] = select (cls ).order_by (func .random ()).limit (1 )
331- if options :
332- statement = statement .options (* options )
333-
334- cursor : Result = await session .execute (statement )
335- try :
336- return cursor .scalars ().one ()
337- except NoResultFound as err :
338- raise ModelDoesNotExistError () from err
0 commit comments