1
1
"""Asynchronous Model objects."""
2
2
3
- from typing import Any , Dict , List
3
+ from typing import Any , Dict , List , Type
4
4
from uuid import UUID
5
5
6
+ from psycopg2 .extras import RealDictRow
7
+
6
8
from db_wrapper .client import AsyncClient
7
9
from .base import (
8
10
ensure_exactly_one ,
11
+ sql ,
9
12
T ,
10
13
CreateABC ,
11
14
ReadABC ,
12
15
UpdateABC ,
13
16
DeleteABC ,
14
17
ModelABC ,
15
- sql ,
16
18
)
17
19
18
20
@@ -23,16 +25,22 @@ class AsyncCreate(CreateABC[T]):
23
25
24
26
_client : AsyncClient
25
27
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 )
28
35
self ._client = client
29
36
30
37
async def one (self , item : T ) -> T :
31
38
"""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 ])
34
42
35
- return result [ 0 ]
43
+ return result
36
44
37
45
38
46
class AsyncRead (ReadABC [T ]):
@@ -42,19 +50,27 @@ class AsyncRead(ReadABC[T]):
42
50
43
51
_client : AsyncClient
44
52
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 )
47
60
self ._client = client
48
61
49
62
async def one_by_id (self , id_value : UUID ) -> T :
50
63
"""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 ))
53
67
54
68
# 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 ])
56
72
57
- return result [ 0 ]
73
+ return result
58
74
59
75
60
76
class AsyncUpdate (UpdateABC [T ]):
@@ -64,8 +80,13 @@ class AsyncUpdate(UpdateABC[T]):
64
80
65
81
_client : AsyncClient
66
82
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 )
69
90
self ._client = client
70
91
71
92
async def one_by_id (self , id_value : str , changes : Dict [str , Any ]) -> T :
@@ -79,12 +100,14 @@ async def one_by_id(self, id_value: str, changes: Dict[str, Any]) -> T:
79
100
Returns:
80
101
full value of row updated
81
102
"""
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 ))
84
106
85
- ensure_exactly_one (result )
107
+ ensure_exactly_one (query_result )
108
+ result : T = self ._return_constructor (** query_result [0 ])
86
109
87
- return result [ 0 ]
110
+ return result
88
111
89
112
90
113
class AsyncDelete (DeleteABC [T ]):
@@ -94,19 +117,26 @@ class AsyncDelete(DeleteABC[T]):
94
117
95
118
_client : AsyncClient
96
119
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 )
99
127
self ._client = client
100
128
101
129
async def one_by_id (self , id_value : str ) -> T :
102
130
"""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 ))
105
134
106
135
# 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 ])
108
138
109
- return result [ 0 ]
139
+ return result
110
140
111
141
112
142
class AsyncModel (ModelABC [T ]):
@@ -122,19 +152,22 @@ class AsyncModel(ModelABC[T]):
122
152
_update : AsyncUpdate [T ]
123
153
_delete : AsyncDelete [T ]
124
154
125
- # PENDS python 3.9 support in pylint
126
- # pylint: disable=unsubscriptable-object
127
155
def __init__ (
128
156
self ,
129
157
client : AsyncClient ,
130
158
table : str ,
159
+ return_constructor : Type [T ],
131
160
) -> None :
132
161
super ().__init__ (client , table )
133
162
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 )
138
171
139
172
@property
140
173
def create (self ) -> AsyncCreate [T ]:
0 commit comments