ormlambda 2.11.2__py3-none-any.whl → 3.7.1__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.
- ormlambda/__init__.py +11 -9
- ormlambda/caster/__init__.py +3 -0
- ormlambda/caster/base_caster.py +69 -0
- ormlambda/caster/caster.py +48 -0
- ormlambda/caster/interfaces/ICaster.py +26 -0
- ormlambda/caster/interfaces/__init__.py +1 -0
- ormlambda/common/__init__.py +1 -1
- ormlambda/common/abstract_classes/__init__.py +3 -3
- ormlambda/common/abstract_classes/decomposition_query.py +117 -319
- ormlambda/common/abstract_classes/non_query_base.py +1 -1
- ormlambda/common/enums/condition_types.py +2 -1
- ormlambda/common/enums/join_type.py +4 -1
- ormlambda/common/errors/__init__.py +15 -2
- ormlambda/common/global_checker.py +28 -0
- ormlambda/common/interfaces/ICustomAlias.py +4 -1
- ormlambda/common/interfaces/IDecompositionQuery.py +9 -34
- ormlambda/common/interfaces/IJoinSelector.py +21 -0
- ormlambda/common/interfaces/__init__.py +4 -6
- ormlambda/components/__init__.py +4 -0
- ormlambda/components/insert/abstract_insert.py +1 -1
- ormlambda/components/select/ISelect.py +17 -0
- ormlambda/components/select/__init__.py +1 -0
- ormlambda/components/update/abstract_update.py +4 -4
- ormlambda/components/upsert/abstract_upsert.py +1 -1
- ormlambda/databases/__init__.py +5 -0
- ormlambda/databases/my_sql/__init__.py +3 -1
- ormlambda/databases/my_sql/caster/__init__.py +1 -0
- ormlambda/databases/my_sql/caster/caster.py +38 -0
- ormlambda/databases/my_sql/caster/read.py +39 -0
- ormlambda/databases/my_sql/caster/types/__init__.py +8 -0
- ormlambda/databases/my_sql/caster/types/bytes.py +31 -0
- ormlambda/databases/my_sql/caster/types/datetime.py +34 -0
- ormlambda/databases/my_sql/caster/types/float.py +31 -0
- ormlambda/databases/my_sql/caster/types/int.py +31 -0
- ormlambda/databases/my_sql/caster/types/iterable.py +31 -0
- ormlambda/databases/my_sql/caster/types/none.py +30 -0
- ormlambda/databases/my_sql/caster/types/point.py +43 -0
- ormlambda/databases/my_sql/caster/types/string.py +31 -0
- ormlambda/databases/my_sql/caster/write.py +37 -0
- ormlambda/databases/my_sql/clauses/ST_AsText.py +36 -0
- ormlambda/databases/my_sql/clauses/ST_Contains.py +31 -0
- ormlambda/databases/my_sql/clauses/__init__.py +6 -4
- ormlambda/databases/my_sql/clauses/alias.py +24 -21
- ormlambda/databases/my_sql/clauses/count.py +32 -28
- ormlambda/databases/my_sql/clauses/create_database.py +3 -4
- ormlambda/databases/my_sql/clauses/delete.py +10 -10
- ormlambda/databases/my_sql/clauses/drop_database.py +3 -5
- ormlambda/databases/my_sql/clauses/drop_table.py +3 -3
- ormlambda/databases/my_sql/clauses/group_by.py +4 -7
- ormlambda/databases/my_sql/clauses/insert.py +33 -19
- ormlambda/databases/my_sql/clauses/joins.py +66 -59
- ormlambda/databases/my_sql/clauses/limit.py +1 -1
- ormlambda/databases/my_sql/clauses/offset.py +1 -1
- ormlambda/databases/my_sql/clauses/order.py +36 -23
- ormlambda/databases/my_sql/clauses/select.py +25 -36
- ormlambda/databases/my_sql/clauses/update.py +38 -13
- ormlambda/databases/my_sql/clauses/upsert.py +2 -2
- ormlambda/databases/my_sql/clauses/where.py +45 -0
- ormlambda/databases/my_sql/functions/concat.py +24 -27
- ormlambda/databases/my_sql/functions/max.py +32 -28
- ormlambda/databases/my_sql/functions/min.py +32 -28
- ormlambda/databases/my_sql/functions/sum.py +32 -28
- ormlambda/databases/my_sql/join_context.py +75 -0
- ormlambda/databases/my_sql/repository/__init__.py +1 -0
- ormlambda/databases/my_sql/{repository.py → repository/repository.py} +114 -74
- ormlambda/databases/my_sql/statements.py +249 -153
- ormlambda/engine/__init__.py +0 -0
- ormlambda/engine/template.py +47 -0
- ormlambda/model/__init__.py +0 -0
- ormlambda/model/base_model.py +37 -0
- ormlambda/repository/__init__.py +2 -0
- ormlambda/repository/base_repository.py +14 -0
- ormlambda/repository/interfaces/IDatabaseConnection.py +12 -0
- ormlambda/{common → repository}/interfaces/IRepositoryBase.py +6 -5
- ormlambda/repository/interfaces/__init__.py +2 -0
- ormlambda/sql/__init__.py +3 -0
- ormlambda/sql/clause_info/__init__.py +3 -0
- ormlambda/sql/clause_info/clause_info.py +434 -0
- ormlambda/sql/clause_info/clause_info_context.py +87 -0
- ormlambda/sql/clause_info/interface/IAggregate.py +10 -0
- ormlambda/sql/clause_info/interface/__init__.py +1 -0
- ormlambda/sql/column.py +126 -0
- ormlambda/sql/comparer.py +156 -0
- ormlambda/sql/foreign_key.py +115 -0
- ormlambda/sql/interfaces/__init__.py +0 -0
- ormlambda/sql/table/__init__.py +1 -0
- ormlambda/{utils → sql/table}/fields.py +6 -5
- ormlambda/{utils → sql/table}/table_constructor.py +43 -91
- ormlambda/sql/types.py +25 -0
- ormlambda/statements/__init__.py +2 -0
- ormlambda/statements/base_statement.py +129 -0
- ormlambda/statements/interfaces/IStatements.py +331 -0
- ormlambda/statements/interfaces/__init__.py +1 -0
- ormlambda/statements/types.py +51 -0
- ormlambda/utils/__init__.py +1 -3
- ormlambda/utils/module_tree/__init__.py +1 -0
- ormlambda/utils/module_tree/dynamic_module.py +20 -14
- {ormlambda-2.11.2.dist-info → ormlambda-3.7.1.dist-info}/METADATA +132 -68
- ormlambda-3.7.1.dist-info/RECORD +117 -0
- ormlambda/common/abstract_classes/abstract_model.py +0 -115
- ormlambda/common/interfaces/IAggregate.py +0 -10
- ormlambda/common/interfaces/IStatements.py +0 -348
- ormlambda/components/where/__init__.py +0 -1
- ormlambda/components/where/abstract_where.py +0 -15
- ormlambda/databases/my_sql/clauses/where_condition.py +0 -222
- ormlambda/model_base.py +0 -36
- ormlambda/utils/column.py +0 -105
- ormlambda/utils/foreign_key.py +0 -81
- ormlambda/utils/lambda_disassembler/__init__.py +0 -4
- ormlambda/utils/lambda_disassembler/dis_types.py +0 -133
- ormlambda/utils/lambda_disassembler/disassembler.py +0 -69
- ormlambda/utils/lambda_disassembler/dtypes.py +0 -103
- ormlambda/utils/lambda_disassembler/name_of.py +0 -41
- ormlambda/utils/lambda_disassembler/nested_element.py +0 -44
- ormlambda/utils/lambda_disassembler/tree_instruction.py +0 -145
- ormlambda-2.11.2.dist-info/RECORD +0 -81
- /ormlambda/{utils → sql}/dtypes.py +0 -0
- {ormlambda-2.11.2.dist-info → ormlambda-3.7.1.dist-info}/LICENSE +0 -0
- {ormlambda-2.11.2.dist-info → ormlambda-3.7.1.dist-info}/WHEEL +0 -0
@@ -1,32 +1,34 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
+
import contextlib
|
2
3
|
from pathlib import Path
|
3
|
-
from typing import Any, Optional, Type, override,
|
4
|
-
import functools
|
4
|
+
from typing import Any, Generator, Iterable, Optional, Type, override, TYPE_CHECKING
|
5
5
|
import shapely as shp
|
6
6
|
|
7
7
|
# from mysql.connector.pooling import MySQLConnectionPool
|
8
|
-
from mysql.connector import MySQLConnection
|
9
|
-
from mysql.connector.pooling import
|
8
|
+
from mysql.connector import MySQLConnection # noqa: F401
|
9
|
+
from mysql.connector.pooling import MySQLConnectionPool # noqa: F401
|
10
|
+
from ormlambda.repository import BaseRepository
|
10
11
|
|
11
12
|
# Custom libraries
|
12
|
-
from ormlambda import IRepositoryBase
|
13
|
-
from ormlambda.
|
13
|
+
from ormlambda.repository import IRepositoryBase
|
14
|
+
from ormlambda.caster import Caster
|
14
15
|
|
15
|
-
from
|
16
|
-
from
|
17
|
-
from
|
16
|
+
from ..clauses import CreateDatabase, TypeExists
|
17
|
+
from ..clauses import DropDatabase
|
18
|
+
from ..clauses import DropTable
|
18
19
|
|
19
20
|
|
20
21
|
if TYPE_CHECKING:
|
21
|
-
from
|
22
|
+
from ormlambda.common.abstract_classes.decomposition_query import ClauseInfo
|
22
23
|
from ormlambda import Table
|
23
|
-
from
|
24
|
+
from ormlambda.databases.my_sql.clauses.select import Select
|
24
25
|
|
25
26
|
type TResponse[TFlavour, *Ts] = TFlavour | tuple[dict[str, tuple[*Ts]]] | tuple[tuple[*Ts]] | tuple[TFlavour]
|
26
27
|
|
27
28
|
|
28
29
|
class Response[TFlavour, *Ts]:
|
29
|
-
def __init__(self, response_values: list[tuple[*Ts]], columns: tuple[str], flavour: Type[TFlavour], model: Optional[Table] = None, select: Optional[Select] = None) -> None:
|
30
|
+
def __init__(self, repository: IRepositoryBase, response_values: list[tuple[*Ts]], columns: tuple[str], flavour: Type[TFlavour], model: Optional[Table] = None, select: Optional[Select] = None) -> None:
|
31
|
+
self._repository: IRepositoryBase = repository
|
30
32
|
self._response_values: list[tuple[*Ts]] = response_values
|
31
33
|
self._columns: tuple[str] = columns
|
32
34
|
self._flavour: Type[TFlavour] = flavour
|
@@ -35,6 +37,7 @@ class Response[TFlavour, *Ts]:
|
|
35
37
|
|
36
38
|
self._response_values_index: int = len(self._response_values)
|
37
39
|
# self.select_values()
|
40
|
+
self._caster = Caster(repository)
|
38
41
|
|
39
42
|
@property
|
40
43
|
def is_one(self) -> bool:
|
@@ -83,7 +86,16 @@ class Response[TFlavour, *Ts]:
|
|
83
86
|
return [list(x) for x in data]
|
84
87
|
|
85
88
|
def _default(**kwargs) -> list[TFlavour]:
|
86
|
-
|
89
|
+
replacer_dicc: dict[str, str] = {x.alias_clause: x.column for x in self._select.all_clauses}
|
90
|
+
|
91
|
+
cleaned_column_names = [replacer_dicc[col] for col in self._columns]
|
92
|
+
|
93
|
+
result = []
|
94
|
+
for attr in data:
|
95
|
+
dicc_attr = dict(zip(cleaned_column_names, attr))
|
96
|
+
result.append(self._flavour(**dicc_attr, **kwargs))
|
97
|
+
|
98
|
+
return result
|
87
99
|
|
88
100
|
selector: dict[Type[object], Any] = {
|
89
101
|
dict: _dict,
|
@@ -92,10 +104,11 @@ class Response[TFlavour, *Ts]:
|
|
92
104
|
list: _list,
|
93
105
|
}
|
94
106
|
|
107
|
+
selector.get(dict)()
|
95
108
|
return selector.get(self._flavour, _default)(**kwargs)
|
96
109
|
|
97
110
|
def _parser_response(self) -> TFlavour:
|
98
|
-
new_response: list[
|
111
|
+
new_response: list[tuple] = []
|
99
112
|
for row in self._response_values:
|
100
113
|
new_row: list = []
|
101
114
|
for i, data in enumerate(row):
|
@@ -105,8 +118,9 @@ class Response[TFlavour, *Ts]:
|
|
105
118
|
new_row = row
|
106
119
|
break
|
107
120
|
else:
|
108
|
-
|
109
|
-
new_row.append(
|
121
|
+
parse_data = self._caster.for_value(data, value_type=clause_info.dtype).from_database
|
122
|
+
new_row.append(parse_data)
|
123
|
+
new_row = tuple(new_row)
|
110
124
|
if not isinstance(new_row, tuple):
|
111
125
|
new_row = tuple(new_row)
|
112
126
|
|
@@ -127,33 +141,38 @@ class Response[TFlavour, *Ts]:
|
|
127
141
|
return data
|
128
142
|
|
129
143
|
|
130
|
-
class MySQLRepository(
|
131
|
-
def get_connection(func: Callable[
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
raise e
|
144
|
+
class MySQLRepository(BaseRepository[MySQLConnectionPool]):
|
145
|
+
# def get_connection[**P, TReturn](func: Callable[Concatenate[MySQLRepository, MySQLConnection, P], TReturn]) -> Callable[P, TReturn]:
|
146
|
+
# def wrapper(self: MySQLRepository, *args: P.args, **kwargs: P.kwargs):
|
147
|
+
# with self.get_connection() as cnx:
|
148
|
+
# try:
|
149
|
+
# return func(self, cnx._cnx, *args, **kwargs)
|
150
|
+
# except Exception as e:
|
151
|
+
# cnx._cnx.rollback()
|
152
|
+
# raise e
|
140
153
|
|
141
|
-
|
154
|
+
# return wrapper
|
142
155
|
|
143
|
-
|
144
|
-
self._data_config: dict[str, Any] = kwargs
|
145
|
-
self._pool: MySQLConnectionPool = self.__create_MySQLConnectionPool()
|
156
|
+
#
|
146
157
|
|
147
|
-
def
|
148
|
-
|
158
|
+
def __init__(self, **kwargs):
|
159
|
+
super().__init__(MySQLConnectionPool, **kwargs)
|
160
|
+
|
161
|
+
@contextlib.contextmanager
|
162
|
+
def get_connection(self) -> Generator[MySQLConnection, None, None]:
|
163
|
+
with self._pool.get_connection() as cnx:
|
164
|
+
try:
|
165
|
+
yield cnx._cnx
|
166
|
+
cnx._cnx.commit()
|
167
|
+
except Exception as exc:
|
168
|
+
cnx._cnx.rollback()
|
169
|
+
raise exc
|
149
170
|
|
150
171
|
@override
|
151
|
-
|
152
|
-
def read_sql[TFlavour](
|
172
|
+
def read_sql[TFlavour: Iterable](
|
153
173
|
self,
|
154
|
-
cnx: MySQLConnection,
|
155
174
|
query: str,
|
156
|
-
flavour: Type[TFlavour] = tuple,
|
175
|
+
flavour: tuple | Type[TFlavour] = tuple,
|
157
176
|
**kwargs,
|
158
177
|
) -> tuple[TFlavour]:
|
159
178
|
"""
|
@@ -169,15 +188,25 @@ class MySQLRepository(IRepositoryBase[MySQLConnection]):
|
|
169
188
|
select: Select = kwargs.pop("select", None)
|
170
189
|
cast_to_tuple: bool = kwargs.pop("cast_to_tuple", True)
|
171
190
|
|
172
|
-
with
|
173
|
-
cursor
|
174
|
-
|
175
|
-
|
176
|
-
|
191
|
+
with self.get_connection() as cnx:
|
192
|
+
with cnx.cursor(buffered=True) as cursor:
|
193
|
+
cursor.execute(query)
|
194
|
+
values: list[tuple] = cursor.fetchall()
|
195
|
+
columns: tuple[str] = cursor.column_names
|
196
|
+
return Response[TFlavour](
|
197
|
+
repository=self,
|
198
|
+
model=model,
|
199
|
+
response_values=values,
|
200
|
+
columns=columns,
|
201
|
+
flavour=flavour,
|
202
|
+
select=select,
|
203
|
+
).response(_tuple=cast_to_tuple, **kwargs)
|
177
204
|
|
178
205
|
# FIXME [ ]: this method does not comply with the implemented interface
|
179
|
-
|
180
|
-
|
206
|
+
def create_tables_code_first(self, path: str | Path) -> None:
|
207
|
+
return
|
208
|
+
from ormlambda.utils.module_tree.dynamic_module import ModuleTree
|
209
|
+
|
181
210
|
if not isinstance(path, Path | str):
|
182
211
|
raise ValueError
|
183
212
|
|
@@ -192,33 +221,30 @@ class MySQLRepository(IRepositoryBase[MySQLConnection]):
|
|
192
221
|
queries_list: list[str] = module_tree.get_queries()
|
193
222
|
|
194
223
|
for query in queries_list:
|
195
|
-
with
|
196
|
-
cursor
|
197
|
-
|
224
|
+
with self.get_connection() as cnx:
|
225
|
+
with cnx.cursor(buffered=True) as cursor:
|
226
|
+
cursor.execute(query)
|
198
227
|
return None
|
199
228
|
|
200
229
|
@override
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
cnx.commit()
|
230
|
+
def executemany_with_values(self, query: str, values) -> None:
|
231
|
+
with self.get_connection() as cnx:
|
232
|
+
with cnx.cursor(buffered=True) as cursor:
|
233
|
+
cursor.executemany(query, values)
|
206
234
|
return None
|
207
235
|
|
208
236
|
@override
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
cnx.commit()
|
237
|
+
def execute_with_values(self, query: str, values) -> None:
|
238
|
+
with self.get_connection() as cnx:
|
239
|
+
with cnx.cursor(buffered=True) as cursor:
|
240
|
+
cursor.execute(query, values)
|
214
241
|
return None
|
215
242
|
|
216
243
|
@override
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
cnx.commit()
|
244
|
+
def execute(self, query: str) -> None:
|
245
|
+
with self.get_connection() as cnx:
|
246
|
+
with cnx.cursor(buffered=True) as cursor:
|
247
|
+
cursor.execute(query)
|
222
248
|
return None
|
223
249
|
|
224
250
|
@override
|
@@ -226,12 +252,21 @@ class MySQLRepository(IRepositoryBase[MySQLConnection]):
|
|
226
252
|
return DropTable(self).execute(name)
|
227
253
|
|
228
254
|
@override
|
229
|
-
|
230
|
-
def database_exists(self, cnx: MySQLConnection, name: str) -> bool:
|
255
|
+
def database_exists(self, name: str) -> bool:
|
231
256
|
query = "SHOW DATABASES LIKE %s;"
|
232
|
-
|
233
|
-
|
257
|
+
temp_config = self._pool._cnx_config
|
258
|
+
|
259
|
+
config_without_db = temp_config.copy()
|
260
|
+
|
261
|
+
if "database" in config_without_db:
|
262
|
+
config_without_db.pop("database")
|
263
|
+
self._pool.set_config(**config_without_db)
|
264
|
+
with self.get_connection() as cnx:
|
265
|
+
with cnx.cursor(buffered=True) as cursor:
|
266
|
+
cursor.execute(query, (name,))
|
234
267
|
res = cursor.fetchmany(1)
|
268
|
+
|
269
|
+
self._pool.set_config(**temp_config)
|
235
270
|
return len(res) > 0
|
236
271
|
|
237
272
|
@override
|
@@ -239,20 +274,25 @@ class MySQLRepository(IRepositoryBase[MySQLConnection]):
|
|
239
274
|
return DropDatabase(self).execute(name)
|
240
275
|
|
241
276
|
@override
|
242
|
-
|
243
|
-
def table_exists(self, cnx: MySQLConnection, name: str) -> bool:
|
244
|
-
if not cnx.database:
|
245
|
-
raise Exception("No database selected")
|
246
|
-
|
277
|
+
def table_exists(self, name: str) -> bool:
|
247
278
|
query = "SHOW TABLES LIKE %s;"
|
248
|
-
with
|
249
|
-
|
279
|
+
with self.get_connection() as cnx:
|
280
|
+
if not cnx.database:
|
281
|
+
raise Exception("No database selected")
|
282
|
+
with cnx.cursor(buffered=True) as cursor:
|
283
|
+
cursor.execute(query, (name,))
|
250
284
|
res = cursor.fetchmany(1)
|
251
285
|
return len(res) > 0
|
252
286
|
|
253
287
|
@override
|
254
288
|
def create_database(self, name: str, if_exists: TypeExists = "fail") -> None:
|
255
|
-
|
289
|
+
temp_config = self._pool._cnx_config
|
290
|
+
|
291
|
+
config_without_db = temp_config.copy()
|
292
|
+
|
293
|
+
if "database" in config_without_db:
|
294
|
+
config_without_db.pop("database")
|
295
|
+
return CreateDatabase(type(self)(**config_without_db)).execute(name, if_exists)
|
256
296
|
|
257
297
|
@property
|
258
298
|
def database(self) -> Optional[str]:
|
@@ -261,4 +301,4 @@ class MySQLRepository(IRepositoryBase[MySQLConnection]):
|
|
261
301
|
@database.setter
|
262
302
|
def database(self, value: str) -> None:
|
263
303
|
self._data_config["database"] = value
|
264
|
-
self._pool
|
304
|
+
self._pool.set_config(**self._data_config)
|