11"""Asynchronous Model objects."""
22
3- from typing import Any , Dict , List
3+ from typing import Any , Dict , List , Type
44from uuid import UUID
55
6+ from psycopg2 .extras import RealDictRow
7+
68from db_wrapper .client import AsyncClient
79from .base import (
810 ensure_exactly_one ,
11+ sql ,
912 T ,
1013 CreateABC ,
1114 ReadABC ,
1215 UpdateABC ,
1316 DeleteABC ,
1417 ModelABC ,
15- sql ,
1618)
1719
1820
@@ -23,16 +25,22 @@ class AsyncCreate(CreateABC[T]):
2325
2426 _client : AsyncClient
2527
26- def __init__ (self , client : AsyncClient , table : sql .Composable ) -> None :
27- super ().__init__ (table )
28+ def __init__ (
29+ self ,
30+ client : AsyncClient ,
31+ table : sql .Composable ,
32+ return_constructor : Type [T ]
33+ ) -> None :
34+ super ().__init__ (table , return_constructor )
2835 self ._client = client
2936
3037 async def one (self , item : T ) -> T :
3138 """Create one new record with a given item."""
32- result : List [T ] = await self ._client .execute_and_return (
33- self ._query_one (item ))
39+ query_result : List [RealDictRow ] = \
40+ await self ._client .execute_and_return (self ._query_one (item ))
41+ result : T = self ._return_constructor (** query_result [0 ])
3442
35- return result [ 0 ]
43+ return result
3644
3745
3846class AsyncRead (ReadABC [T ]):
@@ -42,19 +50,27 @@ class AsyncRead(ReadABC[T]):
4250
4351 _client : AsyncClient
4452
45- def __init__ (self , client : AsyncClient , table : sql .Composable ) -> None :
46- super ().__init__ (table )
53+ def __init__ (
54+ self ,
55+ client : AsyncClient ,
56+ table : sql .Composable ,
57+ return_constructor : Type [T ]
58+ ) -> None :
59+ super ().__init__ (table , return_constructor )
4760 self ._client = client
4861
4962 async def one_by_id (self , id_value : UUID ) -> T :
5063 """Read a row by it's id."""
51- result : List [T ] = await self ._client .execute_and_return (
52- self ._query_one_by_id (id_value ))
64+ query_result : List [RealDictRow ] = \
65+ await self ._client .execute_and_return (
66+ self ._query_one_by_id (id_value ))
5367
5468 # Should only return one item from DB
55- ensure_exactly_one (result )
69+ ensure_exactly_one (query_result )
70+
71+ result : T = self ._return_constructor (** query_result [0 ])
5672
57- return result [ 0 ]
73+ return result
5874
5975
6076class AsyncUpdate (UpdateABC [T ]):
@@ -64,11 +80,16 @@ class AsyncUpdate(UpdateABC[T]):
6480
6581 _client : AsyncClient
6682
67- def __init__ (self , client : AsyncClient , table : sql .Composable ) -> None :
68- super ().__init__ (table )
83+ def __init__ (
84+ self ,
85+ client : AsyncClient ,
86+ table : sql .Composable ,
87+ return_constructor : Type [T ]
88+ ) -> None :
89+ super ().__init__ (table , return_constructor )
6990 self ._client = client
7091
71- async def one_by_id (self , id_value : str , changes : Dict [str , Any ]) -> T :
92+ async def one_by_id (self , id_value : UUID , changes : Dict [str , Any ]) -> T :
7293 """Apply changes to row with given id.
7394
7495 Arguments:
@@ -79,12 +100,14 @@ async def one_by_id(self, id_value: str, changes: Dict[str, Any]) -> T:
79100 Returns:
80101 full value of row updated
81102 """
82- result : List [T ] = await self ._client .execute_and_return (
83- self ._query_one_by_id (id_value , changes ))
103+ query_result : List [RealDictRow ] = \
104+ await self ._client .execute_and_return (
105+ self ._query_one_by_id (id_value , changes ))
84106
85- ensure_exactly_one (result )
107+ ensure_exactly_one (query_result )
108+ result : T = self ._return_constructor (** query_result [0 ])
86109
87- return result [ 0 ]
110+ return result
88111
89112
90113class AsyncDelete (DeleteABC [T ]):
@@ -94,19 +117,26 @@ class AsyncDelete(DeleteABC[T]):
94117
95118 _client : AsyncClient
96119
97- def __init__ (self , client : AsyncClient , table : sql .Composable ) -> None :
98- super ().__init__ (table )
120+ def __init__ (
121+ self ,
122+ client : AsyncClient ,
123+ table : sql .Composable ,
124+ return_constructor : Type [T ]
125+ ) -> None :
126+ super ().__init__ (table , return_constructor )
99127 self ._client = client
100128
101129 async def one_by_id (self , id_value : str ) -> T :
102130 """Delete one record with matching ID."""
103- result : List [T ] = await self ._client .execute_and_return (
104- self ._query_one_by_id (id_value ))
131+ query_result : List [RealDictRow ] = \
132+ await self ._client .execute_and_return (
133+ self ._query_one_by_id (id_value ))
105134
106135 # Should only return one item from DB
107- ensure_exactly_one (result )
136+ ensure_exactly_one (query_result )
137+ result = self ._return_constructor (** query_result [0 ])
108138
109- return result [ 0 ]
139+ return result
110140
111141
112142class AsyncModel (ModelABC [T ]):
@@ -122,19 +152,22 @@ class AsyncModel(ModelABC[T]):
122152 _update : AsyncUpdate [T ]
123153 _delete : AsyncDelete [T ]
124154
125- # PENDS python 3.9 support in pylint
126- # pylint: disable=unsubscriptable-object
127155 def __init__ (
128156 self ,
129157 client : AsyncClient ,
130158 table : str ,
159+ return_constructor : Type [T ],
131160 ) -> None :
132161 super ().__init__ (client , table )
133162
134- self ._create = AsyncCreate [T ](self .client , self .table )
135- self ._read = AsyncRead [T ](self .client , self .table )
136- self ._update = AsyncUpdate [T ](self .client , self .table )
137- self ._delete = AsyncDelete [T ](self .client , self .table )
163+ self ._create = AsyncCreate [T ](
164+ self .client , self .table , return_constructor )
165+ self ._read = AsyncRead [T ](
166+ self .client , self .table , return_constructor )
167+ self ._update = AsyncUpdate [T ](
168+ self .client , self .table , return_constructor )
169+ self ._delete = AsyncDelete [T ](
170+ self .client , self .table , return_constructor )
138171
139172 @property
140173 def create (self ) -> AsyncCreate [T ]:
0 commit comments