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
@@ -0,0 +1,129 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Any, Type, override, Iterable, Literal, TYPE_CHECKING, Optional
|
3
|
+
from collections import defaultdict
|
4
|
+
|
5
|
+
|
6
|
+
from ormlambda.repository import BaseRepository
|
7
|
+
from ormlambda.statements.interfaces import IStatements_two_generic
|
8
|
+
from ormlambda import Table
|
9
|
+
|
10
|
+
from ormlambda.sql.clause_info import AggregateFunctionBase
|
11
|
+
from ormlambda.caster.caster import Caster
|
12
|
+
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase
|
16
|
+
from ormlambda.sql.clause_info import ClauseInfo
|
17
|
+
|
18
|
+
|
19
|
+
ORDER_QUERIES = Literal["select", "join", "where", "order", "with", "group by", "limit", "offset"]
|
20
|
+
|
21
|
+
|
22
|
+
class BaseStatement[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
23
|
+
def __init__(self, model: tuple[T], repository: BaseRepository) -> None:
|
24
|
+
self.__valid_repository(repository)
|
25
|
+
|
26
|
+
self._query: Optional[str] = None
|
27
|
+
self._model: T = model[0] if isinstance(model, Iterable) else model
|
28
|
+
self._models: tuple[T] = self._model if isinstance(model, Iterable) else (model,)
|
29
|
+
self._repository: BaseRepository = repository
|
30
|
+
|
31
|
+
if not issubclass(self._model, Table):
|
32
|
+
# Deben heredar de Table ya que es la forma que tenemos para identificar si estamos pasando una instancia del tipo que corresponde o no cuando llamamos a insert o upsert.
|
33
|
+
# Si no heredase de Table no sabriamos identificar el tipo de dato del que se trata porque al llamar a isinstance, obtendriamos el nombre de la clase que mapea a la tabla, Encargo, Edificio, Presupuesto y no podriamos crear una clase generica
|
34
|
+
raise Exception(f"'{model}' class does not inherit from Table class")
|
35
|
+
|
36
|
+
@staticmethod
|
37
|
+
def __valid_repository(repository: Any) -> bool:
|
38
|
+
if not isinstance(repository, BaseRepository):
|
39
|
+
raise ValueError(f"'repository' attribute does not instance of '{BaseRepository.__name__}'")
|
40
|
+
return True
|
41
|
+
|
42
|
+
def __repr__(self):
|
43
|
+
return f"<Model: {self.__class__.__name__}>"
|
44
|
+
|
45
|
+
def _return_flavour[TValue](self, query, flavour: Type[TValue], select, **kwargs) -> tuple[TValue]:
|
46
|
+
return self._repository.read_sql(query, flavour=flavour, model=self._model, select=select, **kwargs)
|
47
|
+
|
48
|
+
def _return_model(self, select, query: str) -> tuple[tuple[T]]:
|
49
|
+
response_sql = self._repository.read_sql(query, flavour=dict, model=self._model, select=select) # store all columns of the SQL query
|
50
|
+
|
51
|
+
if response_sql and isinstance(response_sql, Iterable):
|
52
|
+
return ClusterQuery(self.repository, select, response_sql).clean_response()
|
53
|
+
|
54
|
+
return response_sql
|
55
|
+
|
56
|
+
@property
|
57
|
+
def query(self) -> str:
|
58
|
+
return self._query
|
59
|
+
|
60
|
+
@property
|
61
|
+
def model(self) -> Type[T]:
|
62
|
+
return self._model
|
63
|
+
|
64
|
+
# TODOL: add *Ts when wil be possible
|
65
|
+
@property
|
66
|
+
def models(self) -> tuple:
|
67
|
+
return self._models
|
68
|
+
|
69
|
+
@property
|
70
|
+
@override
|
71
|
+
def repository(self) -> BaseRepository: ...
|
72
|
+
|
73
|
+
|
74
|
+
class ClusterQuery[T]:
|
75
|
+
def __init__(self, repository: BaseRepository, select: DecompositionQueryBase[T], response_sql: tuple[dict[str, Any]]) -> None:
|
76
|
+
self._repository: BaseRepository = repository
|
77
|
+
self._select: DecompositionQueryBase[T] = select
|
78
|
+
self._response_sql: tuple[dict[str, Any]] = response_sql
|
79
|
+
self._caster = Caster(repository)
|
80
|
+
|
81
|
+
def clean_response(self) -> tuple[dict[Type[Table], tuple[Table, ...]]]:
|
82
|
+
tbl_dicc: dict[Type[Table], list[dict[str, Any]]] = self.__loop_foo()
|
83
|
+
|
84
|
+
response = {}
|
85
|
+
tuple_response = []
|
86
|
+
# it not depend of flavour attr
|
87
|
+
for table, attribute_list in tbl_dicc.items():
|
88
|
+
new_instance = []
|
89
|
+
for attrs in attribute_list:
|
90
|
+
casted_attr = {key: self._caster.for_value(value, table.get_column(key).dtype).from_database for key, value in attrs.items()}
|
91
|
+
new_instance.append(table(**casted_attr))
|
92
|
+
response[table] = tuple(new_instance)
|
93
|
+
tuple_response.append(tuple(new_instance))
|
94
|
+
return tuple(tuple_response)
|
95
|
+
|
96
|
+
def __loop_foo(self) -> dict[Type[Table], list[dict[str, Any]]]:
|
97
|
+
# We'll create a default list of dicts *once* we know how many rows are in _response_sql
|
98
|
+
row_count = len(self._response_sql)
|
99
|
+
|
100
|
+
def make_list_of_dicts() -> list[dict[str, Any]]:
|
101
|
+
return [{} for _ in range(row_count)]
|
102
|
+
|
103
|
+
table_attr_dict = defaultdict(make_list_of_dicts)
|
104
|
+
|
105
|
+
for i, dicc_cols in enumerate(self._response_sql):
|
106
|
+
for clause in self._select.all_clauses:
|
107
|
+
table = clause.table
|
108
|
+
col = clause.column
|
109
|
+
|
110
|
+
if col is None or not hasattr(table, col):
|
111
|
+
agg_methods = self.__get_all_aggregate_method(clause)
|
112
|
+
raise ValueError(f"You cannot use aggregation method like '{agg_methods}' to return model objects. Try specifying 'flavour' attribute as 'dict'.")
|
113
|
+
|
114
|
+
table_attr_dict[table][i][col] = dicc_cols[clause.alias_clause]
|
115
|
+
|
116
|
+
# Convert back to a normal dict if you like (defaultdict is a dict subclass).
|
117
|
+
return dict(table_attr_dict)
|
118
|
+
|
119
|
+
def __get_all_aggregate_method(self, clauses: list[ClauseInfo]) -> str:
|
120
|
+
"""
|
121
|
+
Get the class name of those classes that inherit from 'AggregateFunctionBase' class in order to create a better error message.
|
122
|
+
"""
|
123
|
+
res: set[str] = set()
|
124
|
+
if not isinstance(clauses, Iterable):
|
125
|
+
return clauses.__class__.__name__
|
126
|
+
for clause in clauses:
|
127
|
+
if isinstance(clause, AggregateFunctionBase):
|
128
|
+
res.add(clause.__class__.__name__)
|
129
|
+
return ", ".join(res)
|
@@ -0,0 +1,331 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Any, Callable, Optional, Type, overload, TYPE_CHECKING
|
3
|
+
from enum import Enum
|
4
|
+
from abc import abstractmethod, ABC
|
5
|
+
|
6
|
+
|
7
|
+
from ormlambda.common.enums import JoinType
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from ormlambda.repository import BaseRepository
|
11
|
+
from ormlambda import Table
|
12
|
+
from ormlambda.sql.clause_info import IAggregate
|
13
|
+
from ormlambda.sql.types import TupleJoinType, ColumnType
|
14
|
+
from ormlambda.databases.my_sql.join_context import JoinContext
|
15
|
+
|
16
|
+
from ..types import (
|
17
|
+
OrderTypes,
|
18
|
+
Tuple,
|
19
|
+
Select2,
|
20
|
+
Select3,
|
21
|
+
Select4,
|
22
|
+
Select5,
|
23
|
+
Select6,
|
24
|
+
Select7,
|
25
|
+
Select8,
|
26
|
+
Select9,
|
27
|
+
Select10,
|
28
|
+
TypeExists,
|
29
|
+
WhereTypes,
|
30
|
+
)
|
31
|
+
|
32
|
+
|
33
|
+
class IStatements[T: Table](ABC):
|
34
|
+
@abstractmethod
|
35
|
+
def create_table(self, if_exists: TypeExists = "fail") -> None: ...
|
36
|
+
|
37
|
+
# #TODOL [ ]: We must to implement this mehtod
|
38
|
+
# @abstractmethod
|
39
|
+
# def drop_table(self)->None: ...
|
40
|
+
|
41
|
+
@abstractmethod
|
42
|
+
def table_exists(self) -> bool: ...
|
43
|
+
|
44
|
+
# region insert
|
45
|
+
@overload
|
46
|
+
def insert(self, values: T) -> None:
|
47
|
+
"""
|
48
|
+
PARAMS
|
49
|
+
------
|
50
|
+
- values: Recieves a single object that must match the model's type
|
51
|
+
"""
|
52
|
+
...
|
53
|
+
|
54
|
+
@overload
|
55
|
+
def insert(self, values: list[T]) -> None:
|
56
|
+
"""
|
57
|
+
PARAMS
|
58
|
+
------
|
59
|
+
- values: Recieves a list of the same objects as the model
|
60
|
+
"""
|
61
|
+
...
|
62
|
+
|
63
|
+
@abstractmethod
|
64
|
+
def insert(self, values: T | list[T]) -> None: ...
|
65
|
+
|
66
|
+
# endregion
|
67
|
+
# region upsert
|
68
|
+
@overload
|
69
|
+
def upsert(self, values: T) -> None:
|
70
|
+
"""
|
71
|
+
PARAMS
|
72
|
+
------
|
73
|
+
- values: Recieves a single object that must match the model's type
|
74
|
+
"""
|
75
|
+
...
|
76
|
+
|
77
|
+
@overload
|
78
|
+
def upsert(self, values: list[T]) -> None:
|
79
|
+
"""
|
80
|
+
PARAMS
|
81
|
+
------
|
82
|
+
- values: Recieves a list of the same objects as the model
|
83
|
+
"""
|
84
|
+
...
|
85
|
+
|
86
|
+
@abstractmethod
|
87
|
+
def upsert(self, values: list[T]) -> None:
|
88
|
+
"""
|
89
|
+
Try to insert new values in the table, if they exist, update them
|
90
|
+
"""
|
91
|
+
...
|
92
|
+
|
93
|
+
@overload
|
94
|
+
def update(self, dicc: list[dict[ColumnType, Any]]) -> None:
|
95
|
+
"""
|
96
|
+
An Iterable of ColumnType
|
97
|
+
|
98
|
+
type ColumnType[TProp]:
|
99
|
+
- TProp
|
100
|
+
- Column[TProp]
|
101
|
+
- AsteriskType
|
102
|
+
- tuple[Column]
|
103
|
+
"""
|
104
|
+
...
|
105
|
+
|
106
|
+
@overload
|
107
|
+
def update(self, dicc: dict[ColumnType, Any]) -> None:
|
108
|
+
"""
|
109
|
+
type ColumnType[TProp]:
|
110
|
+
- TProp
|
111
|
+
- Column[TProp]
|
112
|
+
- AsteriskType
|
113
|
+
- tuple[Column]
|
114
|
+
"""
|
115
|
+
...
|
116
|
+
|
117
|
+
@abstractmethod
|
118
|
+
def update(self, dicc) -> None: ...
|
119
|
+
|
120
|
+
# endregion
|
121
|
+
# region limit
|
122
|
+
@abstractmethod
|
123
|
+
def limit(self, number: int) -> IStatements[T]: ...
|
124
|
+
|
125
|
+
# endregion
|
126
|
+
# region offset
|
127
|
+
@abstractmethod
|
128
|
+
def offset(self, number: int) -> IStatements[T]: ...
|
129
|
+
|
130
|
+
# endregion
|
131
|
+
# region count
|
132
|
+
@abstractmethod
|
133
|
+
def count(
|
134
|
+
self,
|
135
|
+
selection: Callable[[T], tuple] = lambda x: "*",
|
136
|
+
alias_clause="count",
|
137
|
+
execute: bool = False,
|
138
|
+
) -> Optional[IStatements[T]]: ...
|
139
|
+
|
140
|
+
# endregion
|
141
|
+
# region delete
|
142
|
+
@overload
|
143
|
+
def delete(self) -> None: ...
|
144
|
+
|
145
|
+
@overload
|
146
|
+
def delete(self, instance: T) -> None: ...
|
147
|
+
|
148
|
+
@overload
|
149
|
+
def delete(self, instance: list[T]) -> None: ...
|
150
|
+
@abstractmethod
|
151
|
+
def delete(self, instance: Optional[T | list[T]] = ...) -> None: ...
|
152
|
+
|
153
|
+
# endregion
|
154
|
+
|
155
|
+
# region where
|
156
|
+
|
157
|
+
@overload
|
158
|
+
def where[LProp, RTable, RProp](self, conditions: Callable[[T], WhereTypes[T, LProp, RTable, RProp]]) -> IStatements[T]: ...
|
159
|
+
|
160
|
+
@abstractmethod
|
161
|
+
def where[LProp, RTable, RProp](self, conditions: WhereTypes[T, LProp, RTable, RProp] = None) -> IStatements[T]: ...
|
162
|
+
|
163
|
+
# endregion
|
164
|
+
# region order
|
165
|
+
@overload
|
166
|
+
def order[TValue](self, _lambda_col: Callable[[T], TValue]) -> IStatements[T]: ...
|
167
|
+
@overload
|
168
|
+
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderTypes) -> IStatements[T]: ...
|
169
|
+
@abstractmethod
|
170
|
+
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderTypes) -> IStatements[T]: ...
|
171
|
+
|
172
|
+
# endregion
|
173
|
+
# region concat
|
174
|
+
@overload
|
175
|
+
def concat[P](self, selector: Callable[[T], tuple[P]]) -> IAggregate: ...
|
176
|
+
|
177
|
+
# endregion
|
178
|
+
# region max
|
179
|
+
@overload
|
180
|
+
def max[TProp](
|
181
|
+
self,
|
182
|
+
column: Callable[[T], TProp],
|
183
|
+
alias: Optional[str] = ...,
|
184
|
+
execute: bool = ...,
|
185
|
+
) -> TProp: ...
|
186
|
+
# endregion
|
187
|
+
# region min
|
188
|
+
@overload
|
189
|
+
def min[TProp](
|
190
|
+
self,
|
191
|
+
column: Callable[[T], TProp],
|
192
|
+
alias: Optional[str] = ...,
|
193
|
+
execute: bool = ...,
|
194
|
+
) -> TProp: ...
|
195
|
+
# endregion
|
196
|
+
# region sum
|
197
|
+
@overload
|
198
|
+
def sum[TProp](
|
199
|
+
self,
|
200
|
+
column: Callable[[T], TProp],
|
201
|
+
alias: Optional[str] = ...,
|
202
|
+
execute: bool = ...,
|
203
|
+
) -> TProp: ...
|
204
|
+
|
205
|
+
@overload
|
206
|
+
def join[FKTable](self, joins: TupleJoinType[FKTable] | tuple[*TupleJoinType[FKTable]]) -> JoinContext[tuple[*TupleJoinType[FKTable]]]: ...
|
207
|
+
|
208
|
+
# endregion
|
209
|
+
# region select
|
210
|
+
type SelectorType[TOri, *T] = Callable[[TOri], tuple[*T]] | tuple[*T]
|
211
|
+
|
212
|
+
@overload
|
213
|
+
def select[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](self, selector: SelectorType[T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], *, by: Optional[Enum] = ...) -> Select10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]: ...
|
214
|
+
@overload
|
215
|
+
def select[T1, T2, T3, T4, T5, T6, T7, T8, T9](self, selector: SelectorType[T, T1, T2, T3, T4, T5, T6, T7, T8, T9], *, by: Optional[Enum] = ...) -> Select9[T1, T2, T3, T4, T5, T6, T7, T8, T9]: ...
|
216
|
+
@overload
|
217
|
+
def select[T1, T2, T3, T4, T5, T6, T7, T8](self, selector: SelectorType[T, T1, T2, T3, T4, T5, T6, T7, T8], *, by: Optional[Enum] = ...) -> Select8[T1, T2, T3, T4, T5, T6, T7, T8]: ...
|
218
|
+
@overload
|
219
|
+
def select[T1, T2, T3, T4, T5, T6, T7](self, selector: SelectorType[T, T1, T2, T3, T4, T5, T6, T7], *, by: Optional[Enum] = ...) -> Select7[T1, T2, T3, T4, T5, T6, T7]: ...
|
220
|
+
@overload
|
221
|
+
def select[T1, T2, T3, T4, T5, T6](self, selector: SelectorType[T, T1, T2, T3, T4, T5, T6], *, by: Optional[Enum] = ...) -> Select6[T1, T2, T3, T4, T5, T6]: ...
|
222
|
+
@overload
|
223
|
+
def select[T1, T2, T3, T4, T5](self, selector: SelectorType[T, T1, T2, T3, T4, T5], *, by: Optional[Enum] = ...) -> Select5[T1, T2, T3, T4, T5]: ...
|
224
|
+
@overload
|
225
|
+
def select[T1, T2, T3, T4](self, selector: SelectorType[T, T1, T2, T3, T4], *, by: Optional[Enum] = ...) -> Select4[T1, T2, T3, T4]: ...
|
226
|
+
@overload
|
227
|
+
def select[T1, T2, T3](self, selector: SelectorType[T, T1, T2, T3], *, by: Optional[Enum] = ...) -> Select3[T1, T2, T3]: ...
|
228
|
+
@overload
|
229
|
+
def select[T1, T2](self, selector: SelectorType[T, T1, T2], *, by: Optional[Enum] = ...) -> Select2[T1, T2]: ...
|
230
|
+
@overload
|
231
|
+
def select[T1](self, selector: SelectorType[T, T1], *, by: Optional[Enum] = ...) -> Tuple[T1]: ...
|
232
|
+
@overload
|
233
|
+
def select[T1](self, selector: Callable[[T], T1], *, by: Optional[Enum] = ...) -> Tuple[T1]: ...
|
234
|
+
@overload
|
235
|
+
def select(self) -> Tuple[T]: ...
|
236
|
+
|
237
|
+
type SelectorFlavourType[T, TResponse] = Optional[Callable[[T], TResponse]]
|
238
|
+
|
239
|
+
# @overload
|
240
|
+
# def select[TFlavour](self, selector: Optional[Callable[[T], tuple]] = ..., *, cast_to_tuple: bool = ..., flavour: Type[TFlavour], by: Optional[Enum] = ..., **kwargs) -> TFlavour: ...
|
241
|
+
@overload
|
242
|
+
def select[TRes](self, selector: SelectorFlavourType[T, TRes] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ..., **kwargs) -> tuple[TRes, ...]: ...
|
243
|
+
@overload
|
244
|
+
def select[*TRes](self, selector: SelectorFlavourType[T, tuple[*TRes]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ..., **kwargs) -> tuple[tuple[*TRes]]: ...
|
245
|
+
@overload
|
246
|
+
def select[TFlavour](self, selector: SelectorFlavourType[T, tuple] = ..., *, flavour: Type[TFlavour], by: Optional[Enum] = ..., **kwargs) -> tuple[TFlavour]: ...
|
247
|
+
|
248
|
+
@abstractmethod
|
249
|
+
def select[TValue, TFlavour, P](self, selector: SelectorFlavourType[T, tuple[TValue, P]] = ..., *, cast_to_tuple: bool = ..., flavour: Type[TFlavour] = ..., by: JoinType = ..., **kwargs): ...
|
250
|
+
|
251
|
+
# endregion
|
252
|
+
# region select_one
|
253
|
+
@overload
|
254
|
+
def select_one(self) -> T: ...
|
255
|
+
@overload
|
256
|
+
def select_one[TFlavour](self, *, by: Optional[Enum] = ..., flavour: Type[TFlavour], **kwargs) -> TFlavour: ...
|
257
|
+
@overload
|
258
|
+
def select_one[T1](self, selector: Callable[[T], T1 | tuple[T1]], *, by: Optional[Enum] = ...) -> T1: ...
|
259
|
+
@overload
|
260
|
+
def select_one[*TRes](self, selector: Callable[[T], tuple[*TRes]], *, by: Optional[Enum] = ...) -> tuple[*TRes]: ...
|
261
|
+
@overload
|
262
|
+
def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = ..., flavour: Type, **kwargs) -> T1: ...
|
263
|
+
@overload
|
264
|
+
def select_one[T1, TFlavour](self, selector: Callable[[T], T1], *, by: Optional[Enum] = ..., flavour: Type[TFlavour], **kwargs) -> TFlavour: ...
|
265
|
+
@overload
|
266
|
+
def select_one[*TRest](self, selector: Callable[[T], tuple[*TRest]], *, by: Optional[Enum] = ..., flavour: Type[tuple], **kwargs) -> tuple[*TRest]: ...
|
267
|
+
@overload
|
268
|
+
def select_one[TFlavour](self, selector: Callable[[T], tuple], *, by: Optional[Enum] = ..., flavour: Type[TFlavour], **kwargs) -> TFlavour: ...
|
269
|
+
@abstractmethod
|
270
|
+
def select_one[TValue, TFlavour, *TRest](
|
271
|
+
self,
|
272
|
+
selector: Optional[Callable[[T], tuple[TValue, *TRest]]] = lambda: None,
|
273
|
+
*,
|
274
|
+
flavour: Type[TFlavour] = ...,
|
275
|
+
by: Optional[Enum] = ...,
|
276
|
+
): ...
|
277
|
+
|
278
|
+
# endregion
|
279
|
+
|
280
|
+
# region first
|
281
|
+
@overload
|
282
|
+
def first(self) -> T: ...
|
283
|
+
@overload
|
284
|
+
def first[TFlavour](self, *, by: Optional[Enum] = ..., flavour: Type[TFlavour], **kwargs) -> TFlavour: ...
|
285
|
+
@overload
|
286
|
+
def first[T1](self, selector: Callable[[T], T1 | tuple[T1]], *, by: Optional[Enum] = ...) -> T1: ...
|
287
|
+
@overload
|
288
|
+
def first[*TRes](self, selector: Callable[[T], tuple[*TRes]], *, by: Optional[Enum] = ...) -> tuple[*TRes]: ...
|
289
|
+
@overload
|
290
|
+
def first[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = ..., flavour: Type, **kwargs) -> T1: ...
|
291
|
+
@overload
|
292
|
+
def first[T1, TFlavour](self, selector: Callable[[T], T1], *, by: Optional[Enum] = ..., flavour: Type[TFlavour], **kwargs) -> TFlavour: ...
|
293
|
+
@overload
|
294
|
+
def first[*TRest](self, selector: Callable[[T], tuple[*TRest]], *, by: Optional[Enum] = ..., flavour: Type[tuple], **kwargs) -> tuple[*TRest]: ...
|
295
|
+
@overload
|
296
|
+
def first[TFlavour](self, selector: Callable[[T], tuple], *, by: Optional[Enum] = ..., flavour: Type[TFlavour], **kwargs) -> TFlavour: ...
|
297
|
+
@abstractmethod
|
298
|
+
def first[TValue, TFlavour, *TRest](
|
299
|
+
self,
|
300
|
+
selector: Optional[Callable[[T], tuple[TValue, *TRest]]] = lambda: None,
|
301
|
+
*,
|
302
|
+
flavour: Type[TFlavour] = ...,
|
303
|
+
by: Optional[Enum] = ...,
|
304
|
+
): ...
|
305
|
+
|
306
|
+
# endregion
|
307
|
+
|
308
|
+
# region group_by
|
309
|
+
@abstractmethod
|
310
|
+
def group_by[TRepo](self, column: Callable[[T], TRepo]) -> IStatements[T]: ...
|
311
|
+
|
312
|
+
# endregion
|
313
|
+
|
314
|
+
@abstractmethod
|
315
|
+
def alias(self, column: Callable[[T], Any], alias: str) -> IStatements[T]: ...
|
316
|
+
|
317
|
+
|
318
|
+
class IStatements_two_generic[T, TPool](IStatements[T]):
|
319
|
+
@property
|
320
|
+
@abstractmethod
|
321
|
+
def repository(self) -> BaseRepository[TPool]: ...
|
322
|
+
|
323
|
+
@property
|
324
|
+
def query(self) -> str: ...
|
325
|
+
|
326
|
+
@property
|
327
|
+
def model(self) -> Type[T]: ...
|
328
|
+
|
329
|
+
# TODOL: add P when wil be possible
|
330
|
+
@property
|
331
|
+
def models(self) -> tuple: ...
|
@@ -0,0 +1 @@
|
|
1
|
+
from .IStatements import IStatements, IStatements_two_generic # noqa: F401
|
@@ -0,0 +1,51 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import (
|
3
|
+
Callable,
|
4
|
+
Iterable,
|
5
|
+
Optional,
|
6
|
+
Literal,
|
7
|
+
Union,
|
8
|
+
TYPE_CHECKING,
|
9
|
+
)
|
10
|
+
import enum
|
11
|
+
|
12
|
+
|
13
|
+
from ormlambda.common.enums import JoinType
|
14
|
+
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
from ormlambda.sql.comparer import Comparer
|
17
|
+
|
18
|
+
type OrderTypes = Literal["ASC", "DESC"] | OrderType | Iterable[OrderType]
|
19
|
+
|
20
|
+
|
21
|
+
class OrderType(enum.Enum):
|
22
|
+
ASC = "ASC"
|
23
|
+
DESC = "DESC"
|
24
|
+
|
25
|
+
|
26
|
+
type Tuple[T] = tuple[T, ...]
|
27
|
+
|
28
|
+
type Select2[T1, T2] = tuple[Tuple[T1], Tuple[T2]]
|
29
|
+
type Select3[T1, T2, T3] = tuple[*Select2[T1, T2], Tuple[T3]]
|
30
|
+
type Select4[T1, T2, T3, T4] = tuple[*Select3[T1, T2, T3], Tuple[T4]]
|
31
|
+
type Select5[T1, T2, T3, T4, T5] = tuple[*Select4[T1, T2, T3, T4], Tuple[T5]]
|
32
|
+
type Select6[T1, T2, T3, T4, T5, T6] = tuple[*Select5[T1, T2, T3, T4, T5], Tuple[T6]]
|
33
|
+
type Select7[T1, T2, T3, T4, T5, T6, T7] = tuple[*Select6[T1, T2, T3, T4, T5, T6], Tuple[T7]]
|
34
|
+
type Select8[T1, T2, T3, T4, T5, T6, T7, T8] = tuple[*Select7[T1, T2, T3, T4, T5, T6, T7], Tuple[T8]]
|
35
|
+
type Select9[T1, T2, T3, T4, T5, T6, T7, T8, T9] = tuple[*Select8[T1, T2, T3, T4, T5, T6, T7, T8], Tuple[T9]]
|
36
|
+
type Select10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] = tuple[*Select9[T1, T2, T3, T4, T5, T6, T7, T8, T9], Tuple[T10]]
|
37
|
+
|
38
|
+
type WhereCondition[T, T1] = Callable[[T, T1], bool]
|
39
|
+
type JoinCondition[T, T1] = tuple[T1, WhereCondition[T, T1], Optional[JoinType]]
|
40
|
+
|
41
|
+
|
42
|
+
# TODOH [x]: This var is duplicated from 'src\ormlambda\databases\my_sql\clauses\create_database.py'
|
43
|
+
type TypeExists = Literal["fail", "replace", "append"]
|
44
|
+
|
45
|
+
|
46
|
+
type WhereTypes[LTable, LProp, RTable, RProp] = Union[
|
47
|
+
bool,
|
48
|
+
Comparer[LTable, LProp, RTable, RProp],
|
49
|
+
tuple[Comparer[LTable, LProp, RTable, RProp], ...],
|
50
|
+
Callable[[LTable], WhereTypes[LTable, LProp, RTable, RProp]],
|
51
|
+
]
|
ormlambda/utils/__init__.py
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
from .dynamic_module import ModuleTree # noqa: F401
|
@@ -1,14 +1,17 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
import sys
|
2
3
|
from pathlib import Path
|
3
|
-
from typing import Optional, Type
|
4
|
+
from typing import Optional, Type, TYPE_CHECKING
|
4
5
|
from collections import defaultdict
|
5
6
|
import importlib.util
|
6
7
|
import inspect
|
7
8
|
import re
|
8
9
|
|
9
|
-
|
10
|
+
if TYPE_CHECKING:
|
11
|
+
from ormlambda import Table
|
10
12
|
|
11
|
-
|
13
|
+
|
14
|
+
# from ormlambda import ForeignKey
|
12
15
|
from .dfs_traversal import DFSTraversal
|
13
16
|
|
14
17
|
|
@@ -176,19 +179,20 @@ class ModuleTree:
|
|
176
179
|
return None
|
177
180
|
|
178
181
|
def order_modules_from_file(self) -> tuple[str]:
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
182
|
+
return
|
183
|
+
# """
|
184
|
+
# Method whose main used is sorting all .py inside of folder to avoid import errors and overall for the creation of tables in SQL, comply with foreign key referenced table
|
185
|
+
# This method's main purpose is to sort all .py inside a folder to avoid import errors and to ensure that tables referenced by foreign key in other tables are created first
|
186
|
+
# """
|
187
|
+
# tables: list[tuple[str, Table]] = self.get_member_table(self.load_module("", self.module_path))
|
184
188
|
|
185
|
-
graph: dict[str, list[str]] = defaultdict(list)
|
186
|
-
for _, tbl in tables:
|
187
|
-
|
189
|
+
# graph: dict[str, list[str]] = defaultdict(list)
|
190
|
+
# for _, tbl in tables:
|
191
|
+
# graph[tbl.__table_name__] = [x.__table_name__ for x in tbl.find_dependent_tables()]
|
188
192
|
|
189
|
-
sorted_tables = DFSTraversal.sort(graph)
|
190
|
-
res = [ForeignKey.MAPPED[x].table_object.create_table_query() for x in sorted_tables]
|
191
|
-
return res
|
193
|
+
# sorted_tables = DFSTraversal.sort(graph)
|
194
|
+
# res = [ForeignKey.MAPPED[x].table_object.create_table_query() for x in sorted_tables]
|
195
|
+
# return res
|
192
196
|
|
193
197
|
@staticmethod
|
194
198
|
def find_module(module_name: str, nodes: list["Node"]) -> Optional["Node"]:
|
@@ -236,4 +240,6 @@ class ModuleTree:
|
|
236
240
|
|
237
241
|
@staticmethod
|
238
242
|
def get_member_table(module) -> list[tuple[str, Type[Table]]]:
|
243
|
+
from ormlambda import Table
|
244
|
+
|
239
245
|
return inspect.getmembers(module, lambda x: inspect.isclass(x) and issubclass(x, Table) and x is not Table)
|