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.
- dapper_sqls/__init__.py +7 -0
- dapper_sqls/_types.py +15 -0
- dapper_sqls/async_dapper/__init__.py +5 -0
- dapper_sqls/async_dapper/async_dapper.py +67 -0
- dapper_sqls/async_dapper/async_executors.py +343 -0
- dapper_sqls/builders/__init__.py +7 -0
- dapper_sqls/builders/model/__init__.py +5 -0
- dapper_sqls/builders/model/model.py +375 -0
- dapper_sqls/builders/model/utils.py +420 -0
- dapper_sqls/builders/query.py +80 -0
- dapper_sqls/builders/stored.py +66 -0
- dapper_sqls/builders/stp.py +133 -0
- dapper_sqls/config.py +109 -0
- dapper_sqls/dapper/__init__.py +6 -0
- dapper_sqls/dapper/dapper.py +66 -0
- dapper_sqls/dapper/executors.py +342 -0
- dapper_sqls/decorators.py +63 -0
- dapper_sqls/models/__init__.py +8 -0
- dapper_sqls/models/base.py +35 -0
- dapper_sqls/models/connection.py +60 -0
- dapper_sqls/models/http.py +10 -0
- dapper_sqls/models/result.py +123 -0
- dapper_sqls/sqlite/__init__.py +4 -0
- dapper_sqls/sqlite/local_database.py +268 -0
- dapper_sqls/sqlite/models.py +30 -0
- dapper_sqls/utils.py +89 -0
- dapper_sqls-0.9.2.dist-info/METADATA +11 -0
- dapper_sqls-0.9.2.dist-info/RECORD +30 -0
- dapper_sqls-0.9.2.dist-info/WHEEL +5 -0
- dapper_sqls-0.9.2.dist-info/top_level.txt +1 -0
dapper_sqls/__init__.py
ADDED
dapper_sqls/_types.py
ADDED
@@ -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
|
+
|