ormlambda 1.2.1__tar.gz → 1.3.0__tar.gz
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-1.2.1 → ormlambda-1.3.0}/PKG-INFO +2 -2
- {ormlambda-1.2.1 → ormlambda-1.3.0}/pyproject.toml +2 -2
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/__init__.py +1 -0
- ormlambda-1.3.0/src/ormlambda/common/abstract_classes/abstract_model.py +87 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/interfaces/IRepositoryBase.py +1 -1
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/repository.py +1 -1
- ormlambda-1.2.1/src/ormlambda/common/abstract_classes/abstract_model.py → ormlambda-1.3.0/src/ormlambda/databases/my_sql/statements.py +47 -139
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/model_base.py +2 -2
- ormlambda-1.2.1/src/ormlambda/databases/my_sql/statements.py +0 -95
- {ormlambda-1.2.1 → ormlambda-1.3.0}/LICENSE +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/README.md +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/abstract_classes/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/abstract_classes/non_query_base.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/abstract_classes/query_base.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/enums/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/enums/condition_types.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/enums/join_type.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/interfaces/INonQueryCommand.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/interfaces/IQueryCommand.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/interfaces/IStatements.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/common/interfaces/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/delete/IDelete.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/delete/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/delete/abstract_delete.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/insert/IInsert.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/insert/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/insert/abstract_insert.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/select/ISelect.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/select/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/select/table_column.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/update/IUpdate.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/update/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/update/abstract_update.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/upsert/IUpsert.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/upsert/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/upsert/abstract_upsert.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/where/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/components/where/abstract_where.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/count.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/create_database.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/delete.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/drop_database.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/drop_table.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/insert.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/joins.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/limit.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/offset.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/order.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/select.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/update.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/upsert.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/where_condition.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/column.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/dtypes.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/foreign_key.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/lambda_disassembler/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/lambda_disassembler/dis_types.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/lambda_disassembler/disassembler.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/lambda_disassembler/dtypes.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/lambda_disassembler/name_of.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/lambda_disassembler/nested_element.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/lambda_disassembler/tree_instruction.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/module_tree/__init__.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/module_tree/dfs_traversal.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/module_tree/dynamic_module.py +0 -0
- {ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/table_constructor.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ormlambda
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.3.0
|
4
4
|
Summary: ORM designed to interact with the database (currently with MySQL) using lambda functions and nested functions
|
5
5
|
Author: p-hzamora
|
6
6
|
Author-email: p.hzamora@icloud.com
|
@@ -8,7 +8,7 @@ Requires-Python: >=3.12,<4.0
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
10
10
|
Requires-Dist: fluent-validation (>=3.1.0,<4.0.0)
|
11
|
-
Requires-Dist: mysql-connector-python (>=
|
11
|
+
Requires-Dist: mysql-connector-python (>=9.0.0,<10.0.0)
|
12
12
|
Description-Content-Type: text/markdown
|
13
13
|
|
14
14
|

|
@@ -3,14 +3,14 @@ line-length = 320
|
|
3
3
|
|
4
4
|
[tool.poetry]
|
5
5
|
name = "ormlambda"
|
6
|
-
version = "1.
|
6
|
+
version = "1.3.0"
|
7
7
|
description = "ORM designed to interact with the database (currently with MySQL) using lambda functions and nested functions"
|
8
8
|
authors = ["p-hzamora <p.hzamora@icloud.com>"]
|
9
9
|
readme = "README.md"
|
10
10
|
|
11
11
|
[tool.poetry.dependencies]
|
12
12
|
python = "^3.12"
|
13
|
-
mysql-connector-python= "^
|
13
|
+
mysql-connector-python= "^9.0.0"
|
14
14
|
fluent-validation = "^3.1.0"
|
15
15
|
|
16
16
|
[tool.poetry.group.test.dependencies]
|
@@ -4,6 +4,7 @@ from .common.enums import ( # noqa: F401
|
|
4
4
|
ConditionType,
|
5
5
|
)
|
6
6
|
|
7
|
+
from .common.abstract_classes import AbstractSQLStatements # noqa: F401
|
7
8
|
from .common.interfaces import IRepositoryBase # noqa: F401
|
8
9
|
from .utils import Table, Column, ForeignKey # noqa: F401
|
9
10
|
from .utils.lambda_disassembler import Disassembler, nameof # noqa: F401
|
@@ -0,0 +1,87 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Any, Type, override, Iterable, Literal, TYPE_CHECKING
|
3
|
+
from collections import defaultdict
|
4
|
+
|
5
|
+
|
6
|
+
from ormlambda.utils import Table
|
7
|
+
from ormlambda.common.interfaces import IQuery, IRepositoryBase, IStatements_two_generic
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from ormlambda.components.select import ISelect
|
11
|
+
from ormlambda.components.select import TableColumn
|
12
|
+
|
13
|
+
|
14
|
+
ORDER_QUERIES = Literal["select", "join", "where", "order", "with", "group by", "limit", "offset"]
|
15
|
+
|
16
|
+
|
17
|
+
class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
18
|
+
__slots__ = ("_model", "_repository", "_query_list")
|
19
|
+
__order__: tuple[str, ...] = ("select", "join", "where", "order", "with", "group by", "limit", "offset")
|
20
|
+
|
21
|
+
def __init__(self, model: T, repository: IRepositoryBase[TRepo]) -> None:
|
22
|
+
self.__valid_repository(repository)
|
23
|
+
|
24
|
+
self._model: T = model
|
25
|
+
self._repository: IRepositoryBase[TRepo] = repository
|
26
|
+
self._query_list: dict[ORDER_QUERIES, list[IQuery]] = defaultdict(list)
|
27
|
+
|
28
|
+
if not issubclass(self._model, Table):
|
29
|
+
# 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.
|
30
|
+
# 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
|
31
|
+
raise Exception(f"'{model}' class does not inherit from Table class")
|
32
|
+
|
33
|
+
@staticmethod
|
34
|
+
def __valid_repository(repository: Any) -> bool:
|
35
|
+
if not isinstance(repository, IRepositoryBase):
|
36
|
+
raise ValueError(f"'repository' attribute does not instance of '{IRepositoryBase.__name__}'")
|
37
|
+
return True
|
38
|
+
|
39
|
+
def __repr__(self):
|
40
|
+
return f"<Model: {self.__class__.__name__}>"
|
41
|
+
|
42
|
+
@property
|
43
|
+
@override
|
44
|
+
def repository(self) -> IRepositoryBase[TRepo]: ...
|
45
|
+
|
46
|
+
def _return_flavour[TValue](self, query, flavour: Type[TValue]) -> tuple[TValue]:
|
47
|
+
return self._repository.read_sql(query, flavour=flavour)
|
48
|
+
|
49
|
+
def _return_model(self, select: ISelect, query: str):
|
50
|
+
response_sql = self._repository.read_sql(query, flavour=dict) # store all columns of the SQL query
|
51
|
+
|
52
|
+
if isinstance(response_sql, Iterable):
|
53
|
+
return ClusterQuery(select, response_sql).clean_response()
|
54
|
+
|
55
|
+
return response_sql
|
56
|
+
|
57
|
+
|
58
|
+
class ClusterQuery:
|
59
|
+
def __init__(self, select: ISelect, response_sql: tuple[dict[str, Any]]) -> None:
|
60
|
+
self._select: ISelect = select
|
61
|
+
self._response_sql: tuple[dict[str, Any]] = response_sql
|
62
|
+
|
63
|
+
def loop_foo(self) -> dict[Type[Table], list[Table]]:
|
64
|
+
# We must ensure to get the valid attributes for each instance
|
65
|
+
table_initialize = defaultdict(list)
|
66
|
+
|
67
|
+
unic_table: dict[Table, list[TableColumn]] = defaultdict(list)
|
68
|
+
for table_col in self._select.select_list:
|
69
|
+
unic_table[table_col._table].append(table_col)
|
70
|
+
|
71
|
+
for table_, table_col in unic_table.items():
|
72
|
+
for dicc_cols in self._response_sql:
|
73
|
+
valid_attr: dict[str, Any] = {}
|
74
|
+
for col in table_col:
|
75
|
+
valid_attr[col.real_column] = dicc_cols[col.alias]
|
76
|
+
# COMMENT: At this point we are going to instantiate Table class with specific attributes getting directly from database
|
77
|
+
table_initialize[table_].append(table_(**valid_attr))
|
78
|
+
return table_initialize
|
79
|
+
|
80
|
+
def clean_response(self) -> tuple[dict[Type[Table], tuple[Table]]]:
|
81
|
+
tbl_dicc: dict[Type[Table], list[Table]] = self.loop_foo()
|
82
|
+
|
83
|
+
# it not depend of flavour attr
|
84
|
+
for key, val in tbl_dicc.items():
|
85
|
+
tbl_dicc[key] = tuple(val)
|
86
|
+
|
87
|
+
return tuple(tbl_dicc.values())
|
@@ -25,7 +25,7 @@ class IRepositoryBase[T](ABC):
|
|
25
25
|
def is_connected(self) -> bool: ...
|
26
26
|
|
27
27
|
@abstractmethod
|
28
|
-
def connect(self, **kwargs: Any) ->
|
28
|
+
def connect(self, **kwargs: Any) -> None: ...
|
29
29
|
|
30
30
|
@abstractmethod
|
31
31
|
def close_connection(self) -> None: ...
|
@@ -85,7 +85,7 @@ class MySQLRepository(IRepositoryBase[MySQLConnection]):
|
|
85
85
|
return self._connection.is_connected()
|
86
86
|
|
87
87
|
@override
|
88
|
-
def connect(self) ->
|
88
|
+
def connect(self) -> None:
|
89
89
|
# return MySQLConnectionPool(pool_name="mypool", pool_size=5, **kwargs)
|
90
90
|
self._connection.connect(**self._data_config)
|
91
91
|
return None
|
@@ -1,98 +1,49 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
-
from typing import
|
3
|
-
from enum import Enum
|
4
|
-
from collections import defaultdict
|
5
|
-
from abc import abstractmethod
|
6
|
-
import inspect
|
7
|
-
|
8
|
-
from ormlambda.utils import ForeignKey, Table
|
9
|
-
|
10
|
-
from ormlambda.common.interfaces import IQuery, IRepositoryBase, IStatements_two_generic
|
2
|
+
from typing import override, Type, TYPE_CHECKING, Any, Callable, Optional
|
11
3
|
|
12
4
|
if TYPE_CHECKING:
|
13
|
-
from ormlambda
|
14
|
-
|
15
|
-
from ormlambda.components.update import UpdateQueryBase
|
5
|
+
from ormlambda import Table
|
16
6
|
from ormlambda.components.select import ISelect
|
17
|
-
from ormlambda.components.delete import DeleteQueryBase
|
18
|
-
from ormlambda.components.upsert import UpsertQueryBase
|
19
|
-
from ormlambda.components.select import TableColumn
|
20
|
-
from ormlambda.components.insert import InsertQueryBase
|
21
7
|
from ormlambda.components.where.abstract_where import AbstractWhere
|
22
|
-
|
8
|
+
from ormlambda.common.interfaces.IStatements import OrderType
|
9
|
+
from ormlambda.common.interfaces import IQuery, IRepositoryBase, IStatements_two_generic
|
10
|
+
|
23
11
|
from ormlambda.databases.my_sql.clauses.select import SelectQuery
|
24
12
|
from ormlambda.databases.my_sql.clauses.count import CountQuery
|
25
13
|
|
26
14
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
15
|
+
from ormlambda import AbstractSQLStatements
|
16
|
+
from .clauses import DeleteQuery
|
17
|
+
from .clauses import InsertQuery
|
18
|
+
from .clauses import JoinSelector
|
19
|
+
from .clauses import LimitQuery
|
20
|
+
from .clauses import OffsetQuery
|
21
|
+
from .clauses import OrderQuery
|
22
|
+
from .clauses import SelectQuery
|
23
|
+
from .clauses import UpsertQuery
|
24
|
+
from .clauses import UpdateQuery
|
25
|
+
from .clauses import WhereCondition
|
26
|
+
from .clauses import CountQuery
|
36
27
|
|
37
|
-
|
28
|
+
from mysql.connector import MySQLConnection
|
38
29
|
|
39
30
|
|
40
|
-
class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
41
|
-
__slots__ = ("_model", "_repository", "_query_list")
|
42
|
-
__order__: tuple[str, ...] = ("select", "join", "where", "order", "with", "group by", "limit", "offset")
|
43
31
|
|
44
|
-
|
45
|
-
self.valid_repository(repository)
|
32
|
+
import inspect
|
46
33
|
|
47
|
-
|
48
|
-
|
49
|
-
self._query_list: dict[ORDER_QUERIES, list[IQuery]] = defaultdict(list)
|
34
|
+
from ormlambda.utils import ForeignKey, Table
|
35
|
+
from ormlambda.common.enums import JoinType
|
50
36
|
|
51
|
-
if not issubclass(self._model, Table):
|
52
|
-
# 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.
|
53
|
-
# 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
|
54
|
-
raise Exception(f"'{model}' class does not inherit from Table class")
|
55
37
|
|
56
|
-
@staticmethod
|
57
|
-
def valid_repository(repository: Any) -> bool:
|
58
|
-
if not isinstance(repository, IRepositoryBase):
|
59
|
-
raise ValueError(f"'repository' attribute does not instance of '{IRepositoryBase.__name__}'")
|
60
|
-
return True
|
61
38
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
@property
|
66
|
-
@abstractmethod
|
67
|
-
def UPSERT_QUERY(self) -> Type[UpsertQueryBase[T, TRepo]]: ...
|
68
|
-
@property
|
69
|
-
@abstractmethod
|
70
|
-
def UPDATE_QUERY(self) -> Type[UpdateQueryBase[T, TRepo]]: ...
|
71
|
-
@property
|
72
|
-
@abstractmethod
|
73
|
-
def DELETE_QUERY(self) -> Type[DeleteQueryBase[T, TRepo]]: ...
|
74
|
-
@property
|
75
|
-
@abstractmethod
|
76
|
-
def LIMIT_QUERY(self) -> Type[IQuery]: ...
|
77
|
-
@property
|
78
|
-
@abstractmethod
|
79
|
-
def OFFSET_QUERY(self) -> Type[IQuery]: ...
|
80
|
-
@property
|
81
|
-
@abstractmethod
|
82
|
-
def JOIN_QUERY(self) -> Type[IQuery]: ...
|
83
|
-
@property
|
84
|
-
@abstractmethod
|
85
|
-
def WHERE_QUERY(self) -> Type[IQuery]: ...
|
86
|
-
@property
|
87
|
-
@abstractmethod
|
88
|
-
def ORDER_QUERY(self) -> Type[IQuery]: ...
|
89
|
-
@property
|
90
|
-
@abstractmethod
|
91
|
-
def SELECT_QUERY(self) -> Type[SelectQuery]: ...
|
39
|
+
class MySQLStatements[T: Table](AbstractSQLStatements[T, MySQLConnection]):
|
40
|
+
def __init__(self, model: T, repository: IRepositoryBase[MySQLConnection]) -> None:
|
41
|
+
super().__init__(model, repository=repository)
|
92
42
|
|
93
43
|
@property
|
94
|
-
@
|
95
|
-
def
|
44
|
+
@override
|
45
|
+
def repository(self) -> IRepositoryBase[MySQLConnection]:
|
46
|
+
return self._repository
|
96
47
|
|
97
48
|
@override
|
98
49
|
def create_table(self) -> None:
|
@@ -106,7 +57,7 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
106
57
|
|
107
58
|
@override
|
108
59
|
def insert(self, instances: T | list[T]) -> None:
|
109
|
-
insert =
|
60
|
+
insert = InsertQuery(self._model, self._repository)
|
110
61
|
insert.insert(instances)
|
111
62
|
insert.execute()
|
112
63
|
self._query_list.clear()
|
@@ -122,7 +73,7 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
122
73
|
# We always going to have a tuple of one element
|
123
74
|
return self.delete(response)
|
124
75
|
|
125
|
-
delete =
|
76
|
+
delete = DeleteQuery(self._model, self._repository)
|
126
77
|
delete.delete(instances)
|
127
78
|
delete.execute()
|
128
79
|
# not necessary to call self._query_list.clear() because select() method already call it
|
@@ -130,7 +81,7 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
130
81
|
|
131
82
|
@override
|
132
83
|
def upsert(self, instances: T | list[T]) -> None:
|
133
|
-
upsert =
|
84
|
+
upsert = UpsertQuery(self._model, self._repository)
|
134
85
|
upsert.upsert(instances)
|
135
86
|
upsert.execute()
|
136
87
|
self._query_list.clear()
|
@@ -138,15 +89,15 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
138
89
|
|
139
90
|
@override
|
140
91
|
def update(self, dicc: dict[str, Any] | list[dict[str, Any]]) -> None:
|
141
|
-
update =
|
92
|
+
update = UpdateQuery(self._model, self._repository, self._query_list["where"])
|
142
93
|
update.update(dicc)
|
143
94
|
update.execute()
|
144
95
|
self._query_list.clear()
|
145
96
|
return None
|
146
97
|
|
147
98
|
@override
|
148
|
-
def limit(self, number: int) ->
|
149
|
-
limit =
|
99
|
+
def limit(self, number: int) -> IStatements_two_generic[T, MySQLConnection]:
|
100
|
+
limit = LimitQuery(number)
|
150
101
|
# Only can be one LIMIT SQL parameter. We only use the last LimitQuery
|
151
102
|
limit_list = self._query_list["limit"]
|
152
103
|
if len(limit_list) > 0:
|
@@ -156,35 +107,35 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
156
107
|
return self
|
157
108
|
|
158
109
|
@override
|
159
|
-
def offset(self, number: int) ->
|
160
|
-
offset =
|
110
|
+
def offset(self, number: int) -> IStatements_two_generic[T, MySQLConnection]:
|
111
|
+
offset = OffsetQuery(number)
|
161
112
|
self._query_list["offset"].append(offset)
|
162
113
|
return self
|
163
114
|
|
164
115
|
@override
|
165
116
|
def count(self) -> int:
|
166
|
-
count_select: IQuery =
|
117
|
+
count_select: IQuery = CountQuery(self._model)
|
167
118
|
self._query_list["select"].append(count_select)
|
168
119
|
query = self.build()
|
169
120
|
return self.repository.read_sql(query)[0][0]
|
170
121
|
|
171
122
|
@override
|
172
|
-
def join(self, table_left: Table, table_right: Table, *, by: str) ->
|
123
|
+
def join(self, table_left: Table, table_right: Table, *, by: str) -> IStatements_two_generic[T, MySQLConnection]:
|
173
124
|
where = ForeignKey.MAPPED[table_left.__table_name__][table_right.__table_name__]
|
174
|
-
join_query =
|
125
|
+
join_query = JoinSelector[table_left, Table](table_left, table_right, JoinType(by), where=where)
|
175
126
|
self._query_list["join"].append(join_query)
|
176
127
|
return self
|
177
128
|
|
178
129
|
@override
|
179
|
-
def where(self, lambda_: Callable[[T], bool] = lambda: None, **kwargs) ->
|
130
|
+
def where(self, lambda_: Callable[[T], bool] = lambda: None, **kwargs) -> IStatements_two_generic[T, MySQLConnection]:
|
180
131
|
# FIXME [x]: I've wrapped self._model into tuple to pass it instance attr. Idk if it's correct
|
181
|
-
where_query =
|
132
|
+
where_query = WhereCondition[T](function=lambda_, instances=(self._model,), **kwargs)
|
182
133
|
self._query_list["where"].append(where_query)
|
183
134
|
return self
|
184
135
|
|
185
136
|
@override
|
186
|
-
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderType) ->
|
187
|
-
order =
|
137
|
+
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderType) -> IStatements_two_generic[T, MySQLConnection]:
|
138
|
+
order = OrderQuery[T](self._model, _lambda_col, order_type)
|
188
139
|
self._query_list["order"].append(order)
|
189
140
|
return self
|
190
141
|
|
@@ -198,7 +149,7 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
198
149
|
if flavour:
|
199
150
|
return result
|
200
151
|
return () if not result else result[0]
|
201
|
-
select: ISelect =
|
152
|
+
select: ISelect = SelectQuery(self._model, select_lambda=selector, by=by)
|
202
153
|
self._query_list["select"].append(select)
|
203
154
|
|
204
155
|
query: str = self.build()
|
@@ -209,17 +160,6 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
209
160
|
return result
|
210
161
|
return self._return_model(select, query)
|
211
162
|
|
212
|
-
def _return_flavour[TValue](self, query, flavour: Type[TValue]) -> tuple[TValue]:
|
213
|
-
return self._repository.read_sql(query, flavour=flavour)
|
214
|
-
|
215
|
-
def _return_model(self, select: ISelect, query: str):
|
216
|
-
response_sql = self._repository.read_sql(query, flavour=dict) # store all columns of the SQL query
|
217
|
-
|
218
|
-
if isinstance(response_sql, Iterable):
|
219
|
-
return ClusterQuery(select, response_sql).clean_response()
|
220
|
-
|
221
|
-
return response_sql
|
222
|
-
|
223
163
|
@override
|
224
164
|
def select_one[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Optional[Type[TFlavour]] = None, by: JoinType = JoinType.INNER_JOIN):
|
225
165
|
self.limit(1)
|
@@ -241,14 +181,14 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
241
181
|
def build(self) -> str:
|
242
182
|
query: str = ""
|
243
183
|
|
244
|
-
self.
|
184
|
+
self.__create_necessary_inner_join()
|
245
185
|
for x in self.__order__:
|
246
186
|
if sub_query := self._query_list.get(x, None):
|
247
|
-
if isinstance(sub_query[0],
|
187
|
+
if isinstance(sub_query[0], WhereCondition):
|
248
188
|
query_ = self.__build_where_clause(sub_query)
|
249
189
|
|
250
190
|
# we must check if any join already exists on query string
|
251
|
-
elif isinstance(sub_query[0],
|
191
|
+
elif isinstance(sub_query[0], JoinSelector):
|
252
192
|
select_query: str = self._query_list["select"][0].query
|
253
193
|
query_ = ""
|
254
194
|
for join in sub_query:
|
@@ -270,7 +210,7 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
270
210
|
query += f" {and_} ({clause})"
|
271
211
|
return query
|
272
212
|
|
273
|
-
def
|
213
|
+
def __create_necessary_inner_join(self) -> None:
|
274
214
|
# When we applied filters in any table that we wont select any column, we need to add manually all neccessary joins to achieve positive result.
|
275
215
|
if "where" not in self._query_list:
|
276
216
|
return None
|
@@ -285,35 +225,3 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
285
225
|
for l_tbl, r_tbl in involved_tables:
|
286
226
|
# FIXME [ ]: Checked what function was called by the self.join method before the change
|
287
227
|
self.join(l_tbl, r_tbl, by="INNER JOIN")
|
288
|
-
|
289
|
-
|
290
|
-
class ClusterQuery:
|
291
|
-
def __init__(self, select: ISelect, response_sql: tuple[dict[str, Any]]) -> None:
|
292
|
-
self._select: ISelect = select
|
293
|
-
self._response_sql: tuple[dict[str, Any]] = response_sql
|
294
|
-
|
295
|
-
def loop_foo(self) -> dict[Type[Table], list[Table]]:
|
296
|
-
# We must ensure to get the valid attributes for each instance
|
297
|
-
table_initialize = defaultdict(list)
|
298
|
-
|
299
|
-
unic_table: dict[Table, list[TableColumn]] = defaultdict(list)
|
300
|
-
for table_col in self._select.select_list:
|
301
|
-
unic_table[table_col._table].append(table_col)
|
302
|
-
|
303
|
-
for table_, table_col in unic_table.items():
|
304
|
-
for dicc_cols in self._response_sql:
|
305
|
-
valid_attr: dict[str, Any] = {}
|
306
|
-
for col in table_col:
|
307
|
-
valid_attr[col.real_column] = dicc_cols[col.alias]
|
308
|
-
# COMMENT: At this point we are going to instantiate Table class with specific attributes getting directly from database
|
309
|
-
table_initialize[table_].append(table_(**valid_attr))
|
310
|
-
return table_initialize
|
311
|
-
|
312
|
-
def clean_response(self) -> tuple[dict[Type[Table], tuple[Table]]]:
|
313
|
-
tbl_dicc: dict[Type[Table], list[Table]] = self.loop_foo()
|
314
|
-
|
315
|
-
# it not depend of flavour attr
|
316
|
-
for key, val in tbl_dicc.items():
|
317
|
-
tbl_dicc[key] = tuple(val)
|
318
|
-
|
319
|
-
return tuple(tbl_dicc.values())
|
@@ -10,7 +10,7 @@ from .databases.my_sql import MySQLStatements, MySQLRepository
|
|
10
10
|
# endregion
|
11
11
|
|
12
12
|
|
13
|
-
class BaseModel[T: Table]:
|
13
|
+
class BaseModel[T: Type[Table]]:
|
14
14
|
"""
|
15
15
|
Class to select the correct AbstractSQLStatements class depends on the repository.
|
16
16
|
|
@@ -27,7 +27,7 @@ class BaseModel[T: Table]:
|
|
27
27
|
cls: AbstractSQLStatements[T, TRepo] = cls.statements_dicc.get(type(repository), None)
|
28
28
|
|
29
29
|
if not cls:
|
30
|
-
raise Exception(f"
|
30
|
+
raise Exception(f"The selected repository '{repository}' does not exist.")
|
31
31
|
|
32
32
|
self = object().__new__(cls)
|
33
33
|
cls.__init__(self, model, repository)
|
@@ -1,95 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
from typing import override, Type, TYPE_CHECKING
|
3
|
-
|
4
|
-
if TYPE_CHECKING:
|
5
|
-
from ormlambda import Table
|
6
|
-
from ormlambda.components.select import ISelect
|
7
|
-
|
8
|
-
from ormlambda.common.abstract_classes import AbstractSQLStatements
|
9
|
-
|
10
|
-
from ormlambda.common.interfaces import IQuery, IRepositoryBase
|
11
|
-
|
12
|
-
from .clauses import DeleteQuery
|
13
|
-
from .clauses import InsertQuery
|
14
|
-
from .clauses import JoinSelector
|
15
|
-
from .clauses import LimitQuery
|
16
|
-
from .clauses import OffsetQuery
|
17
|
-
from .clauses import OrderQuery
|
18
|
-
from .clauses import SelectQuery
|
19
|
-
from .clauses import UpsertQuery
|
20
|
-
from .clauses import UpdateQuery
|
21
|
-
from .clauses import WhereCondition
|
22
|
-
from .clauses import CountQuery
|
23
|
-
|
24
|
-
from mysql.connector import MySQLConnection
|
25
|
-
|
26
|
-
|
27
|
-
class MySQLStatements[T: Table](AbstractSQLStatements[T, MySQLConnection]):
|
28
|
-
def __init__(self, model: T, repository: IRepositoryBase[MySQLConnection]) -> None:
|
29
|
-
super().__init__(model, repository=repository)
|
30
|
-
|
31
|
-
# region Private methods
|
32
|
-
def __repr__(self):
|
33
|
-
return f"<Model: {self.__class__.__name__}>"
|
34
|
-
|
35
|
-
# endregion
|
36
|
-
|
37
|
-
@property
|
38
|
-
@override
|
39
|
-
def INSERT_QUERY(self) -> Type[InsertQuery]:
|
40
|
-
return InsertQuery
|
41
|
-
|
42
|
-
@property
|
43
|
-
@override
|
44
|
-
def UPSERT_QUERY(self) -> Type[UpsertQuery]:
|
45
|
-
return UpsertQuery
|
46
|
-
|
47
|
-
@property
|
48
|
-
@override
|
49
|
-
def UPDATE_QUERY(self) -> Type[UpsertQuery]:
|
50
|
-
return UpdateQuery
|
51
|
-
|
52
|
-
@override
|
53
|
-
@property
|
54
|
-
def DELETE_QUERY(self) -> Type[DeleteQuery]:
|
55
|
-
return DeleteQuery
|
56
|
-
|
57
|
-
@property
|
58
|
-
@override
|
59
|
-
def LIMIT_QUERY(self) -> Type[IQuery]:
|
60
|
-
return LimitQuery
|
61
|
-
|
62
|
-
@property
|
63
|
-
@override
|
64
|
-
def OFFSET_QUERY(self) -> Type[IQuery]:
|
65
|
-
return OffsetQuery
|
66
|
-
|
67
|
-
@property
|
68
|
-
@override
|
69
|
-
def COUNT(self) -> int:
|
70
|
-
return CountQuery
|
71
|
-
|
72
|
-
@property
|
73
|
-
@override
|
74
|
-
def JOIN_QUERY(self) -> Type[IQuery]:
|
75
|
-
return JoinSelector
|
76
|
-
|
77
|
-
@property
|
78
|
-
@override
|
79
|
-
def WHERE_QUERY(self) -> Type[IQuery]:
|
80
|
-
return WhereCondition
|
81
|
-
|
82
|
-
@property
|
83
|
-
@override
|
84
|
-
def ORDER_QUERY(self) -> Type[IQuery]:
|
85
|
-
return OrderQuery
|
86
|
-
|
87
|
-
@property
|
88
|
-
@override
|
89
|
-
def SELECT_QUERY(self) -> Type[ISelect]:
|
90
|
-
return SelectQuery
|
91
|
-
|
92
|
-
@property
|
93
|
-
@override
|
94
|
-
def repository(self) -> IRepositoryBase[MySQLConnection]:
|
95
|
-
return self._repository
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/create_database.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/databases/my_sql/clauses/where_condition.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/lambda_disassembler/nested_element.py
RENAMED
File without changes
|
{ormlambda-1.2.1 → ormlambda-1.3.0}/src/ormlambda/utils/lambda_disassembler/tree_instruction.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|