PK!repka/__init__.pyPK![i  repka/api.pyimport json from abc import abstractmethod from functools import reduce, partial from typing import TypeVar, Optional, Generic, Dict, Sequence, List, cast, Tuple, Callable from aiopg.sa import SAConnection from aiopg.sa.result import ResultProxy from aiopg.sa.transaction import Transaction as SATransaction from pydantic import BaseModel from sqlalchemy import Table from sqlalchemy.sql.elements import BinaryExpression, ClauseElement Created = bool class IdModel(BaseModel): id: Optional[int] T = TypeVar("T", bound=IdModel) class BaseRepository(Generic[T]): def __init__(self, connection: SAConnection) -> None: self.connection = connection @property @abstractmethod def table(self) -> Table: pass @property def serializer(self) -> Callable[[T], Dict]: return cast(Callable[[T], Dict], partial(model_to_primitive, without_id=True)) @property @abstractmethod def deserializer(self) -> Callable[..., T]: # should return callable that acccepts kwargs and return entity (e.g. entity constructor) pass async def insert(self, entity: T) -> T: query = self.table.insert().values(self.serializer(entity)).returning(self.table.c.id) id_ = await self.connection.scalar(query) entity.id = id_ return entity async def insert_many(self, entities: List[T]) -> List[T]: if not entities: return entities query = ( self.table.insert() .values([self.serializer(entity) for entity in entities]) .returning(self.table.c.id) ) rows = await self.connection.execute(query) for index, row in enumerate(rows): entities[index].id = row[0] return entities async def update(self, entity: T) -> T: assert entity.id query = ( self.table.update() .values(self.serializer(entity)) .where(self.table.c.id == entity.id) ) await self.connection.execute(query) return entity async def first(self, *filters: BinaryExpression) -> Optional[T]: query = self.table.select() query = reduce(lambda query_, filter_: query_.where(filter_), filters, query) rows: ResultProxy = await self.connection.execute(query) row = await rows.first() if row: return cast(T, self.deserializer(**row)) return None async def get_by_id(self, entity_id: int) -> Optional[T]: return await self.first(self.table.c.id == entity_id) async def get_or_create( self, filters: Optional[List[BinaryExpression]] = None, defaults: Optional[Dict] = None ) -> Tuple[T, Created]: filters = filters or [] defaults = defaults or {} entity = await self.first(*filters) if entity: return entity, False entity = self.deserializer(**defaults) entity = await self.insert(entity) return entity, True async def get_all( self, filters: Optional[List[BinaryExpression]] = None, orders: Optional[List[BinaryExpression]] = None, ) -> List[T]: filters = filters or [] orders = orders or [] query = self.table.select() query = self._apply_filters(query, filters) query = reduce(lambda query_, order_by: query_.order_by(order_by), orders, query) rows = await self.connection.execute(query) return [cast(T, self.deserializer(**row)) for row in rows] async def delete(self, *filters: BinaryExpression) -> None: query = self.table.delete() query = self._apply_filters(query, filters) await self.connection.execute(query) def _apply_filters( self, query: ClauseElement, filters: Sequence[BinaryExpression] ) -> ClauseElement: return reduce(lambda query_, filter_: query_.where(filter_), filters, query) def execute_in_transaction(self) -> SATransaction: return self.connection.begin() def model_to_primitive(model: BaseModel, without_id: bool = False) -> Dict: data: Dict = json.loads(model.json()) if without_id: data.pop("id", None) return data PK!HڽTUrepka-0.2.0.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!H,Ǎ*repka-0.2.0.dist-info/METADATAUo6~_qH"6X0!.&j Ɋm!Y";Rr4{Ǐ;ߡpZ0#v/ ``|˴ mpY9pt}K!̹ƃFZDRÖ`[/ج'L GLcc!d~2{m. ]#ϯsa\K$cq4zWW>1(P"&_<<9|#AH]n z?/|ػK>+PN&5tk js'Ijaߘ^TH7h#KnZ+GRTs >+Λb?],:P2fl\2ZnoAf iچy/28m\;O‚lmtQ ­Pm(AXl'ts\=xYѴLE~GEPV$>)`k/#9kczvwyULg=Z4=(}ta*쁨j[ᜳN+BX/zX;S N_CrLۼ-)rB(A4D+|*5{L\T"ytdںhL}IYJ cM:Ä=BK&v<W.f.Qz?M >V uRB=MEsp$B\Vӵ , O9C#jJ;nHג{A [ye ): c R4hKC`]UŸG2_q:\`4$λ+#CH l10{DsI2wUO9~=]H8{I3,5?B_blN"+,C~ X_k(sIנ$BZ}F(r#7sFiL뭍魓K