dapper-sqls 0.9.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ from .dapper import Dapper
2
+ from .async_dapper import AsyncDapper
3
+ from .models import TableBaseModel
4
+ from .builders import ModelBuilder, StpBuilder, AsyncStpBuilder
5
+ from .sqlite import LocalDatabase
6
+
7
+
dapper_sqls/_types.py ADDED
@@ -0,0 +1,15 @@
1
+ from typing import TypeVar
2
+ from enum import Enum
3
+
4
+
5
+ T = TypeVar('T')
6
+
7
+ class ExecType(Enum):
8
+ send = "send"
9
+ fetchone = "fetchone"
10
+ fetchall = "fetchall"
11
+
12
+
13
+
14
+
15
+
@@ -0,0 +1,5 @@
1
+ from .async_dapper import AsyncDapper
2
+
3
+
4
+
5
+
@@ -0,0 +1,67 @@
1
+ # -*- coding: latin -*-
2
+ from .._types import T
3
+ from ..config import Config
4
+ from ..models import Result
5
+ from typing import Type, overload
6
+ from .async_executors import AsyncQuery, AsyncStored
7
+
8
+ class AsyncDapper(object):
9
+
10
+ def __init__(self, server: str , database : str , username : str, password : str, sql_version : int = None, api_environment = False, default_attempts = 1, default_wait_timeout = 2):
11
+ self._config = Config(server, database, username, password, sql_version, api_environment, default_attempts, default_wait_timeout)
12
+
13
+ async def query(self, attempts : int = None, wait_timeout : int = None):
14
+ attempts = attempts if attempts else self.config.default_attempts
15
+ wait_timeout = wait_timeout if wait_timeout else self.config.default_wait_timeout
16
+ return AsyncQuery(self.config.connectionStringDataQuery.get(), attempts, wait_timeout, self._config.sql_version, self._config.api_environment)
17
+
18
+ async def stored(self, attempts : int = None, wait_timeout : int = None):
19
+ attempts = attempts if attempts else self.config.default_attempts
20
+ wait_timeout = wait_timeout if wait_timeout else self.config.default_wait_timeout
21
+ return AsyncStored(self.config.connectionStringDataStored.get() , attempts, wait_timeout, self._config.sql_version, self._config.api_environment)
22
+
23
+ @property
24
+ def config(self):
25
+ return self._config
26
+
27
+ @overload
28
+ @staticmethod
29
+ def load(model : Type[T], dict_data : dict) -> T:
30
+ pass
31
+
32
+ @overload
33
+ @staticmethod
34
+ def load(model : Type[T], list_dict_data : list[dict]) -> list[T]:
35
+ pass
36
+
37
+ @overload
38
+ @staticmethod
39
+ def load(model : Type[T], fetchone : Result.Fetchone) -> T:
40
+ pass
41
+
42
+ @overload
43
+ @staticmethod
44
+ def load(model : Type[T], fetchall : Result.Fetchall) -> list[T]:
45
+ pass
46
+
47
+ @staticmethod
48
+ def load(*args) -> object | list[object]:
49
+ model = args[0]
50
+ data = args[1]
51
+ if isinstance(args[1], dict) or isinstance(args[1], Result.Fetchone):
52
+ if isinstance(args[1], Result.Fetchone):
53
+ data = data.dict
54
+ if all(value is None for value in data.values()):
55
+ return model()
56
+
57
+ return model(**data)
58
+
59
+ if isinstance(args[1], Result.Fetchall):
60
+ data = data.list_dict
61
+
62
+ return [model(**d) for d in data]
63
+
64
+
65
+
66
+
67
+
@@ -0,0 +1,343 @@
1
+ # -*- coding: latin -*-
2
+ import aioodbc, asyncio
3
+ from typing import overload
4
+ from datetime import datetime
5
+ from abc import ABC, abstractmethod
6
+ from ..models import ConnectionStringData, Result, UnavailableServiceException, BaseUpdate
7
+ from .._types import T, ExecType
8
+ from ..config import Config
9
+ from ..builders import QueryBuilder, StoredBuilder
10
+ from ..utils import Utils
11
+
12
+ class AsyncBaseExecutor(ABC):
13
+ def __init__(self, connectionStringData : ConnectionStringData, attempts : int, wait_timeout : int, sql_version : int | None, api_environment : bool):
14
+ self._connectionStringData = connectionStringData
15
+ self._cursor = None
16
+ self._connection = None
17
+ self._wait_timeout = wait_timeout
18
+ self._attempts = attempts
19
+ self._sql_version = sql_version
20
+ self._api_environment = api_environment
21
+
22
+ async def __aenter__(self):
23
+ cs_data = self._connectionStringData
24
+ for n in range(self._attempts):
25
+ odbc_version = f'ODBC Driver {self._sql_version} for SQL Server'
26
+ if not self._sql_version:
27
+ all_driver_versions = Config.get_all_odbc_driver_versions()
28
+ if all_driver_versions:
29
+ odbc_version = all_driver_versions[0]
30
+ else:
31
+ raise RuntimeError("Nenhuma vers�o do driver ODBC for SQL Server foi encontrada.")
32
+ try:
33
+ connection_string = f'DRIVER={{{odbc_version}}};SERVER={cs_data.server};DATABASE={cs_data.database};UID={cs_data.username};PWD={cs_data.password}'
34
+ self._connection = await aioodbc.connect(dsn=connection_string)
35
+ self._cursor = await self._connection.cursor()
36
+
37
+ except Exception as e:
38
+ print(e)
39
+ print(f'Erro na conex�o com a base de dados, nova tentativa em {self._wait_timeout}s')
40
+ await asyncio.sleep(self._wait_timeout)
41
+
42
+ return self
43
+
44
+ async def __aexit__(self, *args):
45
+ if self._cursor:
46
+ await self._cursor.close()
47
+ if self._connection:
48
+ await self._connection.close()
49
+
50
+ @property
51
+ def connectionStringData(self):
52
+ return self._connectionStringData
53
+
54
+ @property
55
+ def api_environment(self):
56
+ return self._api_environment
57
+
58
+ @property
59
+ def sql_version(self):
60
+ return self._sql_version
61
+
62
+ @property
63
+ async def cursor(self):
64
+ if not self._cursor:
65
+ if self._connection:
66
+ self._cursor = await self._connection.cursor()
67
+ return self._cursor
68
+
69
+ @property
70
+ def connection(self):
71
+ if self._connection:
72
+ return self._connection
73
+
74
+ @property
75
+ def attempts(self):
76
+ return self._attempts
77
+
78
+ @attempts.setter
79
+ def attempts(self, value):
80
+ if isinstance(value, int):
81
+ self._attempts = value
82
+ else:
83
+ raise ValueError("O n�mero de tentativas deve ser um n�mero inteiro.")
84
+
85
+ @property
86
+ def wait_timeout(self):
87
+ return self._wait_timeout
88
+
89
+ @wait_timeout.setter
90
+ def wait_timeout(self, value):
91
+ if isinstance(value, int):
92
+ self._wait_timeout = value
93
+ else:
94
+ raise ValueError("O tempo de espera deve ser um n�mero inteiro.")
95
+
96
+ @abstractmethod
97
+ async def _exec_(self, connection, operation_sql, exec_type):
98
+ pass
99
+
100
+ class AsyncQueryUpdate(BaseUpdate):
101
+ def __init__(self, executor : AsyncBaseExecutor, model : T):
102
+ super().__init__(executor, model)
103
+
104
+ @overload
105
+ async def where(self, model : T) -> Result.Send:
106
+ pass
107
+
108
+ @overload
109
+ async def where(self, query : str) -> Result.Send:
110
+ pass
111
+
112
+ async def where(self, *args) -> Result.Send:
113
+ query = QueryBuilder.update(self._set_data, *args)
114
+ return await self.executor._exec_(self.executor.connection , query, ExecType.send)
115
+
116
+
117
+ class AsyncQuery(AsyncBaseExecutor):
118
+
119
+ def __init__(self, connectionStringData : ConnectionStringData, attempts : int, wait_timeout : int, sql_version : int | None, api_environment : bool):
120
+ super().__init__(connectionStringData, attempts, wait_timeout, sql_version, api_environment)
121
+
122
+ @overload
123
+ async def fetchone(self, query : str) -> Result.Fetchone:
124
+ pass
125
+
126
+ @overload
127
+ async def fetchone(self, model : T, additional_sql : str = "") -> T:
128
+ pass
129
+
130
+ async def fetchone(self, *args, **kwargs) -> T | Result.Fetchone:
131
+ args = Utils.args_query(*args, **kwargs)
132
+ if args.model:
133
+ args.query = QueryBuilder.select(args.model, args.additional_sql, args.select_top)
134
+
135
+ result = await self._exec_(self._connection, args.query, ExecType.fetchone)
136
+ if args.model:
137
+ return args.model.__class__(**result.dict) if result.success else args.model.__class__()
138
+ return result
139
+
140
+ @overload
141
+ async def fetchall(self, query : str) -> Result.Fetchall:
142
+ pass
143
+
144
+ @overload
145
+ async def fetchall(self, model : T, additional_sql : str = "", select_top : int = None) -> list[T]:
146
+ pass
147
+
148
+ async def fetchall(self, *args, **kwargs) -> list[T] | Result.Fetchall:
149
+ args = Utils.args_query(*args, **kwargs)
150
+ if args.model:
151
+ args.query = QueryBuilder.select(args.model, args.additional_sql, args.select_top)
152
+
153
+ result = await self._exec_(self._connection, args.query, ExecType.fetchall)
154
+ if args.model:
155
+ return [args.model.__class__(**r) for r in result.list_dict] if result.success else []
156
+ return result
157
+
158
+ async def execute(self, query : str) -> Result.Send:
159
+ return await self._exec_(self._connection, query, ExecType.send)
160
+
161
+ async def delete(self, model: T) -> Result.Send:
162
+ query = QueryBuilder.delete(model)
163
+ return await self._exec_(self._connection, query, ExecType.send)
164
+
165
+ def update(self, model: T):
166
+ return AsyncQueryUpdate(self, model)
167
+
168
+ async def insert(self, model: T, name_column_id = 'Id') -> Result.Insert:
169
+ insert_data = model.model_dump()
170
+ if name_column_id not in insert_data:
171
+ name_column_id = next(iter(insert_data.keys()))
172
+
173
+ query = QueryBuilder.insert(model, name_column_id)
174
+ result : Result.Fetchone = await self._exec_(self._connection, query, ExecType.fetchone)
175
+ if result.success:
176
+ return Result.Insert(result.dict.get('Id', 0), result.status_code, result.message)
177
+ return Result.Insert(0, result.status_code, result.message)
178
+
179
+ async def _exec_(self, connection, query_sql : str, exec_type : ExecType):
180
+
181
+ if not self._cursor:
182
+ if self._api_environment:
183
+ raise UnavailableServiceException()
184
+
185
+ if exec_type == ExecType.fetchone:
186
+ return Result.Fetchone(None, None, 503)
187
+ elif exec_type == ExecType.fetchall:
188
+ return Result.Fetchall(None, None, 503)
189
+ elif exec_type == ExecType.send:
190
+ return Result.Send(False, 503)
191
+
192
+ # executar
193
+ response = await self._cursor.execute(query_sql)
194
+
195
+ # ober resultado se nessesario
196
+ if exec_type == ExecType.fetchone:
197
+ result = Result.Fetchone(self._cursor, await response.fetchone())
198
+
199
+ elif exec_type == ExecType.fetchall:
200
+ result = Result.Fetchall(self._cursor, await response.fetchall())
201
+ elif exec_type == ExecType.send:
202
+ result = Result.Send(True)
203
+
204
+ # fazer o commit
205
+ await connection.commit()
206
+
207
+ # retorna o resultado
208
+ return result
209
+
210
+
211
+ class AsyncStoredUpdate(BaseUpdate):
212
+ def __init__(self, executor : AsyncBaseExecutor, model : T):
213
+ super().__init__(executor, model)
214
+
215
+ async def where(self, data : T) -> Result.Send:
216
+ query, params = StoredBuilder.update(self._set_data, data)
217
+ return await self.executor._exec_(self.executor.connection, (query, *params), ExecType.send)
218
+
219
+
220
+ class AsyncStored(AsyncBaseExecutor):
221
+
222
+ def __init__(self, connectionStringData : ConnectionStringData, attempts : int, wait_timeout : int,sql_version : int | None, api_environment : bool):
223
+ super().__init__(connectionStringData, attempts, wait_timeout, sql_version, api_environment)
224
+
225
+ @overload
226
+ async def fetchone(self, query : str, params : list | tuple) -> Result.Fetchone:
227
+ pass
228
+
229
+ @overload
230
+ async def fetchone(self, query : str, *params : int | str | datetime) -> Result.Fetchone:
231
+ pass
232
+
233
+ @overload
234
+ async def fetchone(self, model : T, additional_sql : str = "") -> T:
235
+ pass
236
+
237
+ async def fetchone(self, *args, **kwargs) -> T | Result.Fetchone:
238
+ args = Utils.args_stored(*args, **kwargs)
239
+ if args.model:
240
+ args.query, args.params = StoredBuilder.select(args.model, args.additional_sql, args.select_top)
241
+
242
+ result = await self._exec_(self._connection, (args.query, *args.params), ExecType.fetchone)
243
+ if args.model:
244
+ return args.model.__class__(**result.dict) if result.success else args.model.__class__()
245
+ return result
246
+
247
+ @overload
248
+ async def fetchall(self, query : str, params : list | tuple) -> Result.Fetchall:
249
+ pass
250
+
251
+ @overload
252
+ async def fetchall(self, query : str, *params : int | str | datetime) -> Result.Fetchall:
253
+ pass
254
+
255
+ @overload
256
+ async def fetchall(self, model : T, additional_sql : str = "", select_top : int = None) -> list[T]:
257
+ pass
258
+
259
+ async def fetchall(self, *args, **kwargs) -> list[T] | Result.Fetchall:
260
+ args = Utils.args_stored(*args, **kwargs)
261
+ if args.model:
262
+ args.query, args.params = StoredBuilder.select(args.model, args.additional_sql, args.select_top)
263
+
264
+ result = await self._exec_(self._connection, (args.query, *args.params), ExecType.fetchall)
265
+ if args.model:
266
+ return [args.model.__class__(**r) for r in result.list_dict] if result.success else []
267
+ return result
268
+
269
+ @overload
270
+ async def execute(self, query : str, *params : str | int) -> Result.Send:
271
+ pass
272
+
273
+ @overload
274
+ async def execute(self, query : str, params : list | tuple) -> Result.Send:
275
+ pass
276
+
277
+ async def execute(self, *args) -> Result.Send:
278
+ query = args[0]
279
+ params = args[1:]
280
+ if len(params) == 1 and isinstance(params[0], (list, tuple)):
281
+ params = params[0]
282
+ return await self._exec_(self._connection, (query, *params), ExecType.send)
283
+
284
+ async def delete(self, model: T) -> Result.Send:
285
+ query, params = StoredBuilder.delete(model)
286
+ return await self._exec_(self._connection, (query, *params), ExecType.send)
287
+
288
+ def update(self, model: T):
289
+ return AsyncStoredUpdate(self, model)
290
+
291
+ async def insert(self, model: T, name_column_id = 'Id') -> Result.Insert:
292
+ insert_data = model.model_dump()
293
+ if name_column_id not in insert_data:
294
+ name_column_id = next(iter(insert_data.keys()))
295
+
296
+ query, params = StoredBuilder.insert(model, name_column_id)
297
+ result : Result.Fetchone = await self._exec_(self._connection, (query, *params), ExecType.fetchone)
298
+ if result.success:
299
+ return Result.Insert(result.dict.get('Id', 0), result.status_code, result.message)
300
+ return Result.Insert(0, result.status_code, result.message)
301
+
302
+ async def _exec_(self, connection , stored_procedure : tuple, exec_type : ExecType):
303
+
304
+ if not self._cursor:
305
+ if self._api_environment:
306
+ raise UnavailableServiceException()
307
+
308
+ if exec_type == ExecType.fetchone:
309
+ return Result.Fetchone(None, None, 503)
310
+ elif exec_type == ExecType.fetchall:
311
+ return Result.Fetchall(None, None, 503)
312
+ elif exec_type == ExecType.send:
313
+ return Result.Send(False, 503)
314
+
315
+ try:
316
+ # executar
317
+ response = await self._cursor.execute(*stored_procedure)
318
+
319
+ # ober resultado se nessesario
320
+ if exec_type == ExecType.fetchone:
321
+ result = Result.Fetchone(self._cursor, await response.fetchone())
322
+ elif exec_type == ExecType.fetchall:
323
+ result = Result.Fetchall(self._cursor, await response.fetchall())
324
+ elif exec_type == ExecType.send:
325
+ result = Result.Send(True)
326
+
327
+ # fazer o commit
328
+ await connection.commit()
329
+
330
+ except Exception as ex:
331
+ if exec_type == ExecType.fetchone:
332
+ return Result.Fetchone(None, None, 503, str(ex))
333
+ elif exec_type == ExecType.fetchall:
334
+ return Result.Fetchall(None, None, 503, str(ex))
335
+ elif exec_type == ExecType.send:
336
+ return Result.Send(False, 503, str(ex))
337
+
338
+ # retorna o resultado
339
+ return result
340
+
341
+
342
+
343
+
@@ -0,0 +1,7 @@
1
+ from .query import QueryBuilder
2
+ from .stored import StoredBuilder
3
+ from .model import ModelBuilder
4
+ from .stp import StpBuilder, AsyncStpBuilder
5
+
6
+
7
+
@@ -0,0 +1,5 @@
1
+ from .model import ModelBuilder
2
+
3
+
4
+
5
+