ormlambda 2.7.2__tar.gz → 2.9.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.
Files changed (82) hide show
  1. {ormlambda-2.7.2 → ormlambda-2.9.0}/PKG-INFO +3 -2
  2. {ormlambda-2.7.2 → ormlambda-2.9.0}/pyproject.toml +4 -2
  3. ormlambda-2.9.0/src/ormlambda/__init__.py +20 -0
  4. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/abstract_model.py +16 -17
  5. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/decomposition_query.py +23 -0
  6. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IStatements.py +68 -36
  7. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/__init__.py +1 -1
  8. {ormlambda-2.7.2/src/ormlambda/databases/my_sql/functions → ormlambda-2.9.0/src/ormlambda/databases/my_sql/clauses}/group_by.py +0 -2
  9. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/insert.py +24 -12
  10. ormlambda-2.9.0/src/ormlambda/databases/my_sql/clauses/order.py +47 -0
  11. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/select.py +8 -4
  12. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/update.py +11 -17
  13. ormlambda-2.9.0/src/ormlambda/databases/my_sql/functions/__init__.py +5 -0
  14. ormlambda-2.9.0/src/ormlambda/databases/my_sql/functions/sum.py +39 -0
  15. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/repository.py +56 -6
  16. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/statements.py +45 -25
  17. ormlambda-2.9.0/src/ormlambda/utils/column.py +105 -0
  18. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/dtypes.py +4 -12
  19. ormlambda-2.9.0/src/ormlambda/utils/fields.py +60 -0
  20. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/table_constructor.py +67 -95
  21. ormlambda-2.7.2/src/ormlambda/__init__.py +0 -11
  22. ormlambda-2.7.2/src/ormlambda/databases/my_sql/clauses/order.py +0 -33
  23. ormlambda-2.7.2/src/ormlambda/databases/my_sql/functions/__init__.py +0 -4
  24. ormlambda-2.7.2/src/ormlambda/utils/column.py +0 -66
  25. {ormlambda-2.7.2 → ormlambda-2.9.0}/LICENSE +0 -0
  26. {ormlambda-2.7.2 → ormlambda-2.9.0}/README.md +0 -0
  27. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/__init__.py +0 -0
  28. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/__init__.py +0 -0
  29. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/non_query_base.py +0 -0
  30. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/query_base.py +0 -0
  31. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/enums/__init__.py +0 -0
  32. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/enums/condition_types.py +0 -0
  33. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/enums/join_type.py +0 -0
  34. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IAggregate.py +0 -0
  35. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IDecompositionQuery.py +0 -0
  36. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/INonQueryCommand.py +0 -0
  37. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IQueryCommand.py +0 -0
  38. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IRepositoryBase.py +0 -0
  39. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/__init__.py +0 -0
  40. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/__init__.py +0 -0
  41. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/delete/IDelete.py +0 -0
  42. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/delete/__init__.py +0 -0
  43. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/delete/abstract_delete.py +0 -0
  44. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/insert/IInsert.py +0 -0
  45. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/insert/__init__.py +0 -0
  46. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/insert/abstract_insert.py +0 -0
  47. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/update/IUpdate.py +0 -0
  48. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/update/__init__.py +0 -0
  49. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/update/abstract_update.py +0 -0
  50. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/upsert/IUpsert.py +0 -0
  51. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/upsert/__init__.py +0 -0
  52. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/upsert/abstract_upsert.py +0 -0
  53. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/where/__init__.py +0 -0
  54. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/where/abstract_where.py +0 -0
  55. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/__init__.py +0 -0
  56. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/__init__.py +0 -0
  57. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/count.py +0 -0
  58. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/create_database.py +0 -0
  59. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/delete.py +0 -0
  60. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/drop_database.py +0 -0
  61. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/drop_table.py +0 -0
  62. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/joins.py +0 -0
  63. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/limit.py +0 -0
  64. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/offset.py +0 -0
  65. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/upsert.py +0 -0
  66. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/where_condition.py +0 -0
  67. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/functions/concat.py +0 -0
  68. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/functions/max.py +0 -0
  69. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/functions/min.py +0 -0
  70. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/model_base.py +0 -0
  71. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/__init__.py +0 -0
  72. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/foreign_key.py +0 -0
  73. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/__init__.py +0 -0
  74. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/dis_types.py +0 -0
  75. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/disassembler.py +0 -0
  76. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/dtypes.py +0 -0
  77. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/name_of.py +0 -0
  78. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/nested_element.py +0 -0
  79. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/tree_instruction.py +0 -0
  80. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/module_tree/__init__.py +0 -0
  81. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/module_tree/dfs_traversal.py +0 -0
  82. {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/module_tree/dynamic_module.py +0 -0
@@ -1,14 +1,15 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ormlambda
3
- Version: 2.7.2
3
+ Version: 2.9.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
7
7
  Requires-Python: >=3.12,<4.0
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.12
10
- Requires-Dist: fluent-validation (>=3.1.0,<4.0.0)
10
+ Requires-Dist: fluent-validation (==4.3.1)
11
11
  Requires-Dist: mysql-connector-python (>=9.0.0,<10.0.0)
12
+ Requires-Dist: shapely (>=2.0.6,<3.0.0)
12
13
  Description-Content-Type: text/markdown
13
14
 
14
15
  ![PyPI version](https://img.shields.io/pypi/v/ormlambda.svg)
@@ -3,7 +3,7 @@ line-length = 320
3
3
 
4
4
  [tool.poetry]
5
5
  name = "ormlambda"
6
- version = "2.7.2"
6
+ version = "2.9.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"
@@ -11,12 +11,14 @@ readme = "README.md"
11
11
  [tool.poetry.dependencies]
12
12
  python = "^3.12"
13
13
  mysql-connector-python= "^9.0.0"
14
- fluent-validation = "^3.1.0"
14
+ fluent-validation = "4.3.1"
15
+ shapely = "^2.0.6"
15
16
 
16
17
  [tool.poetry.group.test.dependencies]
17
18
  pandas = "^2.2.2"
18
19
  ruff = "^0.4.5"
19
20
  python-decouple = "^3.8"
21
+ parameterized = "^0.9.0"
20
22
 
21
23
 
22
24
  [build-system]
@@ -0,0 +1,20 @@
1
+ # region enums
2
+ from .common.enums import (
3
+ JoinType as JoinType,
4
+ ConditionType as ConditionType,
5
+ )
6
+ from ormlambda.common.interfaces.IStatements import OrderType as OrderType
7
+ # endregion
8
+
9
+ from .common.abstract_classes import AbstractSQLStatements as AbstractSQLStatements
10
+ from .common.interfaces import IRepositoryBase as IRepositoryBase
11
+ from .utils import (
12
+ Table as Table,
13
+ Column as Column,
14
+ ForeignKey as ForeignKey,
15
+ )
16
+ from .utils.lambda_disassembler import (
17
+ Disassembler as Disassembler,
18
+ nameof as nameof,
19
+ )
20
+ from .model_base import BaseModel as BaseModel # COMMENT: to avoid relative import we need to import BaseModel after import Table,Column, ForeignKey, IRepositoryBase and Disassembler
@@ -10,7 +10,6 @@ from ormlambda.common.interfaces.IAggregate import IAggregate
10
10
 
11
11
  if TYPE_CHECKING:
12
12
  from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase
13
- from ormlambda.components.select import ISelect
14
13
  from ormlambda.common.abstract_classes.decomposition_query import ClauseInfo
15
14
 
16
15
 
@@ -46,11 +45,11 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
46
45
  @override
47
46
  def repository(self) -> IRepositoryBase[TRepo]: ...
48
47
 
49
- def _return_flavour[TValue](self, query, flavour: Type[TValue]) -> tuple[TValue]:
50
- return self._repository.read_sql(query, flavour=flavour)
48
+ def _return_flavour[TValue](self, query, flavour: Type[TValue], select) -> tuple[TValue]:
49
+ return self._repository.read_sql(query, flavour=flavour, model=self._model, select=select)
51
50
 
52
- def _return_model(self, select: ISelect, query: str):
53
- response_sql = self._repository.read_sql(query, flavour=dict) # store all columns of the SQL query
51
+ def _return_model(self, select, query: str):
52
+ response_sql = self._repository.read_sql(query, flavour=dict, model=self._model, select=select) # store all columns of the SQL query
54
53
 
55
54
  if isinstance(response_sql, Iterable):
56
55
  return ClusterQuery[T](select, response_sql).clean_response()
@@ -66,7 +65,16 @@ class ClusterQuery[T]:
66
65
  self._select: DecompositionQueryBase[T] = select
67
66
  self._response_sql: tuple[dict[str, Any]] = response_sql
68
67
 
69
- def loop_foo(self) -> dict[Type[Table], list[Table]]:
68
+ def clean_response(self) -> tuple[dict[Type[Table], tuple[Table]]]:
69
+ tbl_dicc: dict[Type[Table], list[Table]] = self.__loop_foo()
70
+
71
+ # it not depend of flavour attr
72
+ for key, val in tbl_dicc.items():
73
+ tbl_dicc[key] = tuple(val)
74
+
75
+ return tuple(tbl_dicc.values())
76
+
77
+ def __loop_foo(self) -> dict[Type[Table], list[Table]]:
70
78
  # We must ensure to get the valid attributes for each instance
71
79
  table_initialize = defaultdict(list)
72
80
 
@@ -75,7 +83,7 @@ class ClusterQuery[T]:
75
83
  valid_attr: dict[str, Any] = {}
76
84
  for clause in clauses:
77
85
  if not hasattr(table, clause.column):
78
- agg_methods = self.get_all_aggregate_method(clauses)
86
+ agg_methods = self.__get_all_aggregate_method(clauses)
79
87
  raise ValueError(f"You cannot use aggregation method like '{agg_methods}' to return model objects. Try specifying 'flavour' attribute as 'dict'.")
80
88
  valid_attr[clause.column] = dicc_cols[clause.alias]
81
89
 
@@ -83,7 +91,7 @@ class ClusterQuery[T]:
83
91
  table_initialize[table].append(table(**valid_attr))
84
92
  return table_initialize
85
93
 
86
- def get_all_aggregate_method(self, clauses: list[ClauseInfo]) -> str:
94
+ def __get_all_aggregate_method(self, clauses: list[ClauseInfo]) -> str:
87
95
  res: set[str] = set()
88
96
 
89
97
  for clause in clauses:
@@ -91,12 +99,3 @@ class ClusterQuery[T]:
91
99
  if isinstance(row, IAggregate):
92
100
  res.add(row.__class__.__name__)
93
101
  return ", ".join(res)
94
-
95
- def clean_response(self) -> tuple[dict[Type[Table], tuple[Table]]]:
96
- tbl_dicc: dict[Type[Table], list[Table]] = self.loop_foo()
97
-
98
- # it not depend of flavour attr
99
- for key, val in tbl_dicc.items():
100
- tbl_dicc[key] = tuple(val)
101
-
102
- return tuple(tbl_dicc.values())
@@ -44,6 +44,13 @@ class ClauseInfo[T: tp.Type[Table]]:
44
44
  def query(self) -> str:
45
45
  return self._query
46
46
 
47
+ @property
48
+ def dtype[TProp](self) -> tp.Optional[tp.Type[TProp]]:
49
+ try:
50
+ return self._table.get_column(self.column).dtype
51
+ except ValueError:
52
+ return None
53
+
47
54
  def _resolve_column(self, data: ClauseDataType) -> str:
48
55
  if isinstance(data, property):
49
56
  return self._table.__properties_mapped__[data]
@@ -73,6 +80,17 @@ class ClauseInfo[T: tp.Type[Table]]:
73
80
 
74
81
 
75
82
  class DecompositionQueryBase[T: tp.Type[Table]](IDecompositionQuery[T]):
83
+ @tp.overload
84
+ def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]]) -> None: ...
85
+ @tp.overload
86
+ def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]], *, alias: bool = ...) -> None: ...
87
+ @tp.overload
88
+ def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]], *, alias: bool = ..., alias_name: tp.Optional[str] = ...) -> None: ...
89
+ @tp.overload
90
+ def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]], *, alias: bool = ..., alias_name: tp.Optional[str] = ..., by: JoinType = ...) -> None: ...
91
+ @tp.overload
92
+ def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]], *, alias: bool = ..., alias_name: tp.Optional[str] = ..., by: JoinType = ..., replace_asterisk_char: bool = ...) -> None: ...
93
+
76
94
  def __init__[*Ts](
77
95
  self,
78
96
  table: T,
@@ -98,6 +116,11 @@ class DecompositionQueryBase[T: tp.Type[Table]](IDecompositionQuery[T]):
98
116
 
99
117
  self.__clauses_list_generetor(lambda_query)
100
118
 
119
+ def __getitem__(self, key: str) -> ClauseInfo:
120
+ for clause in self._all_clauses:
121
+ if clause.alias == key:
122
+ return clause
123
+
101
124
  def alias_children_resolver[Tclause: tp.Type[Table]](self, clause_info: ClauseInfo[Tclause]):
102
125
  DEFAULT_ALIAS: str = f"{clause_info._table.__table_name__}_{clause_info._column}"
103
126
 
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
  from typing import Any, Callable, Iterable, Optional, Literal, Type, Union, overload, TYPE_CHECKING, TypeVar
3
3
  from enum import Enum
4
4
  from abc import abstractmethod, ABC
5
+ import enum
5
6
 
6
7
  from .IRepositoryBase import IRepositoryBase
7
8
  from ormlambda.common.enums import JoinType
@@ -10,7 +11,15 @@ if TYPE_CHECKING:
10
11
  from ormlambda import Table
11
12
  from .IAggregate import IAggregate
12
13
 
13
- OrderType = Literal["ASC", "DESC"]
14
+
15
+ class OrderType(enum.Enum):
16
+ ASC = "ASC"
17
+ DESC = "DESC"
18
+
19
+
20
+ OrderTypeString = Literal["ASC", "DESC"]
21
+
22
+ OrderTypes = OrderTypeString | OrderType | Iterable[OrderType]
14
23
 
15
24
  # TODOH: This var is duplicated from 'src\ormlambda\databases\my_sql\clauses\create_database.py'
16
25
  TypeExists = Literal["fail", "replace", "append"]
@@ -91,7 +100,12 @@ class IStatements[T: Table](ABC):
91
100
  # endregion
92
101
  # region count
93
102
  @abstractmethod
94
- def count(self, selection: Callable[[T], property]) -> int: ...
103
+ def count(
104
+ self,
105
+ selection: Callable[[T], property],
106
+ alias: bool = ...,
107
+ alias_name: Optional[str] = ...,
108
+ ) -> int: ...
95
109
 
96
110
  # endregion
97
111
  # region delete
@@ -104,7 +118,7 @@ class IStatements[T: Table](ABC):
104
118
  @overload
105
119
  def delete(self, instance: list[T]) -> None: ...
106
120
  @abstractmethod
107
- def delete(self, instance: Optional[T | list[T]] = None) -> None: ...
121
+ def delete(self, instance: Optional[T | list[T]] = ...) -> None: ...
108
122
 
109
123
  # endregion
110
124
  # region join
@@ -150,9 +164,9 @@ class IStatements[T: Table](ABC):
150
164
  @overload
151
165
  def order[TValue](self, _lambda_col: Callable[[T], TValue]) -> IStatements[T]: ...
152
166
  @overload
153
- def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderType) -> IStatements[T]: ...
167
+ def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderTypes) -> IStatements[T]: ...
154
168
  @abstractmethod
155
- def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderType) -> IStatements[T]: ...
169
+ def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderTypes) -> IStatements[T]: ...
156
170
 
157
171
  # endregion
158
172
  # region concat
@@ -162,76 +176,94 @@ class IStatements[T: Table](ABC):
162
176
  # endregion
163
177
  # region max
164
178
  @overload
165
- def max[TProp](self, column: Callable[[T], TProp], alias: bool = True, alias_name: str = "max") -> TProp: ...
166
- @overload
167
- def min[TProp](self, column: Callable[[T], TProp], alias: bool = True, alias_name: str = "min") -> TProp: ...
168
-
179
+ def max[TProp](
180
+ self,
181
+ column: Callable[[T], TProp],
182
+ alias: bool = ...,
183
+ alias_name: Optional[str] = ...,
184
+ ) -> TProp: ...
185
+ # endregion
186
+ # region min
187
+ @overload
188
+ def min[TProp](
189
+ self,
190
+ column: Callable[[T], TProp],
191
+ alias: bool = ...,
192
+ alias_name: Optional[str] = ...,
193
+ ) -> TProp: ...
194
+ # endregion
195
+ # region sum
196
+ @overload
197
+ def sum[TProp](
198
+ self,
199
+ column: Callable[[T], TProp],
200
+ alias: bool = ...,
201
+ alias_name: Optional[str] = ...,
202
+ ) -> TProp: ...
169
203
  # endregion
170
204
  # region select
171
205
  @overload
172
206
  def select(self) -> tuple[T, ...]: ...
173
207
  @overload
174
- def select[T1](self, selector: Callable[[T], T1], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[T1, ...]]: ...
208
+ def select[T1](self, selector: Callable[[T], T1], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...]]: ...
175
209
  @overload
176
- def select[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[T1, ...]]: ...
210
+ def select[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...]]: ...
177
211
  @overload
178
- def select[T1, T2](self, selector: Callable[[T], tuple[T1, T2]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[T1, ...], tuple[T2, ...]]: ...
212
+ def select[T1, T2](self, selector: Callable[[T], tuple[T1, T2]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...]]: ...
179
213
  @overload
180
- def select[T1, T2, T3](self, selector: Callable[[T], tuple[T1, T2, T3]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...]]: ...
214
+ def select[T1, T2, T3](self, selector: Callable[[T], tuple[T1, T2, T3]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...]]: ...
181
215
  @overload
182
- def select[T1, T2, T3, T4](self, selector: Callable[[T], tuple[T1, T2, T3, T4]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...]]: ...
216
+ def select[T1, T2, T3, T4](self, selector: Callable[[T], tuple[T1, T2, T3, T4]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...]]: ...
183
217
  @overload
184
- def select[T1, T2, T3, T4, T5](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...]]: ...
218
+ def select[T1, T2, T3, T4, T5](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...]]: ...
185
219
  @overload
186
- def select[T1, T2, T3, T4, T5, T6](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...]]: ...
220
+ def select[T1, T2, T3, T4, T5, T6](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...]]: ...
187
221
  @overload
188
- def select[T1, T2, T3, T4, T5, T6, T7](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...]]: ...
222
+ def select[T1, T2, T3, T4, T5, T6, T7](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...]]: ...
189
223
  @overload
190
- def select[T1, T2, T3, T4, T5, T6, T7, T8](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...]]: ...
224
+ def select[T1, T2, T3, T4, T5, T6, T7, T8](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...]]: ...
191
225
  @overload
192
- def select[T1, T2, T3, T4, T5, T6, T7, T8, T9](
193
- self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9]], *, by: Optional[Enum] = JoinType.INNER_JOIN
194
- ) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...], tuple[T9, ...]]: ...
226
+ def select[T1, T2, T3, T4, T5, T6, T7, T8, T9](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...], tuple[T9, ...]]: ...
195
227
  @overload
196
228
  def select[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](
197
- self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]], *, by: Optional[Enum] = JoinType.INNER_JOIN
229
+ self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]], *, by: Optional[Enum] = ...
198
230
  ) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...], tuple[T9, ...], tuple[T10, ...]]: ...
199
231
  @overload
200
- def select[Ts](self, selector: Optional[Callable[[T], Ts]] = None, *, flavour: Type[tuple], by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[Ts, ...]: ...
232
+ def select[Ts](self, selector: Optional[Callable[[T], Ts]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ...) -> tuple[Ts, ...]: ...
201
233
  @overload
202
- def select[Ts](self, selector: Optional[Callable[[T], tuple[Ts]]] = None, *, flavour: Type[tuple], by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[Ts, ...]: ...
234
+ def select[Ts](self, selector: Optional[Callable[[T], tuple[Ts]]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ...) -> tuple[Ts, ...]: ...
203
235
  @overload
204
- def select[*Ts](self, selector: Optional[Callable[[T], tuple[*Ts]]] = None, *, flavour: Type[tuple], by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[tuple[*Ts]]: ...
236
+ def select[*Ts](self, selector: Optional[Callable[[T], tuple[*Ts]]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ...) -> tuple[tuple[*Ts]]: ...
205
237
  @overload
206
- def select[TFlavour](self, selector: Optional[Callable[[T], tuple]] = None, *, flavour: Type[TFlavour], by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[TFlavour]: ...
238
+ def select[TFlavour](self, selector: Optional[Callable[[T], tuple]] = ..., *, flavour: Type[TFlavour], by: Optional[Enum] = ...) -> tuple[TFlavour]: ...
207
239
  @abstractmethod
208
- def select[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Type[TFlavour] = None, by: JoinType = JoinType.INNER_JOIN): ...
240
+ def select[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = ..., *, flavour: Type[TFlavour] = ..., by: JoinType = ...): ...
209
241
 
210
242
  # endregion
211
243
  # region select_one
212
244
  @overload
213
245
  def select_one(self) -> T: ...
214
246
  @overload
215
- def select_one[TFlavour](self, *, by: Optional[Enum] = JoinType.INNER_JOIN, flavour: Type[TFlavour]) -> TFlavour: ...
247
+ def select_one[TFlavour](self, *, by: Optional[Enum] = ..., flavour: Type[TFlavour]) -> TFlavour: ...
216
248
  @overload
217
- def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> T1: ...
249
+ def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = ...) -> T1: ...
218
250
  @overload
219
- def select_one[*Ts](self, selector: Callable[[T], tuple[*Ts]], *, by: Optional[Enum] = JoinType.INNER_JOIN) -> tuple[*Ts]: ...
251
+ def select_one[*Ts](self, selector: Callable[[T], tuple[*Ts]], *, by: Optional[Enum] = ...) -> tuple[*Ts]: ...
220
252
  @overload
221
- def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = JoinType.INNER_JOIN, flavour: Type) -> T1: ...
253
+ def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = ..., flavour: Type) -> T1: ...
222
254
  @overload
223
- def select_one[T1, TFlavour](self, selector: Callable[[T], T1], *, by: Optional[Enum] = JoinType.INNER_JOIN, flavour: Type[TFlavour]) -> T1: ...
255
+ def select_one[T1, TFlavour](self, selector: Callable[[T], T1], *, by: Optional[Enum] = ..., flavour: Type[TFlavour]) -> T1: ...
224
256
  @overload
225
- def select_one[*Ts](self, selector: Callable[[T], tuple[*Ts]], *, by: Optional[Enum] = JoinType.INNER_JOIN, flavour: Type[tuple]) -> tuple[*Ts]: ...
257
+ def select_one[*Ts](self, selector: Callable[[T], tuple[*Ts]], *, by: Optional[Enum] = ..., flavour: Type[tuple]) -> tuple[*Ts]: ...
226
258
  @overload
227
- def select_one[TFlavour](self, selector: Callable[[T], tuple], *, by: Optional[Enum] = JoinType.INNER_JOIN, flavour: Type[TFlavour]) -> TFlavour: ...
259
+ def select_one[TFlavour](self, selector: Callable[[T], tuple], *, by: Optional[Enum] = ..., flavour: Type[TFlavour]) -> TFlavour: ...
228
260
  @abstractmethod
229
- def select_one[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Type[TFlavour] = None, by: Optional[Enum] = JoinType.INNER_JOIN): ...
261
+ def select_one[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Type[TFlavour] = ..., by: Optional[Enum] = ...): ...
230
262
 
231
263
  # endregion
232
264
  # region group_by
233
265
  @abstractmethod
234
- def group_by[TRepo, *Ts](self, column: Callable[[T], TRepo], select_query: Callable[[T], tuple[*Ts]]) -> tuple[tuple[*Ts]]: ...
266
+ def group_by[TRepo, *Ts](self, column: Callable[[T], TRepo]) -> IStatements[T]: ...
235
267
 
236
268
  # endregion
237
269
 
@@ -13,4 +13,4 @@ from .update import UpdateQuery as UpdateQuery
13
13
  from .upsert import UpsertQuery as UpsertQuery
14
14
  from .where_condition import WhereCondition as WhereCondition
15
15
  from .count import Count as Count
16
- from ..functions.group_by import GroupBy as GroupBy
16
+ from .group_by import GroupBy as GroupBy
@@ -25,8 +25,6 @@ class GroupBy[T: tp.Type[Table], TProp](DecompositionQueryBase[T], IAggregate[T]
25
25
  by=by,
26
26
  )
27
27
 
28
- self._column: TProp = column
29
-
30
28
  def alias_children_resolver[Tclause: tp.Type[Table]](self, clause_info: ClauseInfo[Tclause]):
31
29
  return None
32
30
 
@@ -1,4 +1,4 @@
1
- from typing import Any, override, Iterable
1
+ from typing import override, Iterable
2
2
  from mysql.connector import MySQLConnection
3
3
 
4
4
  from ormlambda import Table
@@ -24,13 +24,24 @@ class InsertQuery[T: Table](InsertQueryBase[T, IRepositoryBase[MySQLConnection]]
24
24
 
25
25
  @override
26
26
  def insert(self, instances: T | list[T]) -> None:
27
- new_dict_list: list[dict[str, Any]] = []
28
- self.__fill_dict_list(new_dict_list, instances)
29
- cols_tuple = new_dict_list[0].keys()
30
- join_cols = ", ".join(cols_tuple)
31
- unknown_rows = f'({", ".join(["%s"]*len(cols_tuple))})' # The number of "%s" must match the dict 'dicc_0' length
27
+ valid_cols: list[list[Column]] = []
28
+ self.__fill_dict_list(valid_cols, instances)
32
29
 
33
- self._values = [tuple(x.values()) for x in new_dict_list]
30
+ col_names: list[str] = []
31
+ wildcards: list[str] = []
32
+ col_values: list[list[str]] = []
33
+ for i, cols in enumerate(valid_cols):
34
+ col_values.append([])
35
+ for col in cols:
36
+ if i == 0:
37
+ col_names.append(col.column_name)
38
+ wildcards.append(col.placeholder)
39
+ col_values[-1].append(col.column_value_to_query)
40
+
41
+ join_cols = ", ".join(col_names)
42
+ unknown_rows = f'({", ".join(wildcards)})' # The number of "%s" must match the dict 'dicc_0' length
43
+
44
+ self._values = [tuple(x) for x in col_values]
34
45
  self._query = f"{self.CLAUSE} {self._model.__table_name__} {f'({join_cols})'} VALUES {unknown_rows}"
35
46
  return None
36
47
 
@@ -55,17 +66,18 @@ class InsertQuery[T: Table](InsertQueryBase[T, IRepositoryBase[MySQLConnection]]
55
66
  return False
56
67
  return True
57
68
 
58
- def __fill_dict_list(self, list_dict: list[dict], values: T | list[T]):
69
+ def __fill_dict_list[TProp](self, list_dict: list[str, TProp], values: T | list[T]) -> list[Column]:
59
70
  if issubclass(values.__class__, Table):
60
- dicc: dict = {}
71
+ new_list = []
61
72
  for col in values.__dict__.values():
62
73
  if isinstance(col, Column) and self.__is_valid(col):
63
- dicc.update({col.column_name: col.column_value})
64
- list_dict.append(dicc)
65
- return list_dict
74
+ new_list.append(col)
75
+
76
+ list_dict.append(new_list)
66
77
 
67
78
  elif isinstance(values, Iterable):
68
79
  for x in values:
69
80
  self.__fill_dict_list(list_dict, x)
70
81
  else:
71
82
  raise Exception(f"Tipo de dato'{type(values)}' no esperado")
83
+ return None
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+ from typing import override, Callable, TYPE_CHECKING, Any, Iterable
3
+
4
+ from ormlambda.common.abstract_classes.decomposition_query import ClauseInfo
5
+
6
+
7
+ if TYPE_CHECKING:
8
+ from ormlambda import Table
9
+
10
+ from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase
11
+ from ormlambda.common.interfaces.IStatements import OrderType
12
+
13
+
14
+ class OrderQuery[T: Table](DecompositionQueryBase[T]):
15
+ ORDER = "ORDER BY"
16
+
17
+ def __init__[*Ts](self, instance: T, lambda_query: Callable[[Any], tuple[*Ts]], order_type: Iterable[OrderType]) -> None:
18
+ super().__init__(instance, lambda_query)
19
+
20
+ if isinstance(order_type, str) or not isinstance(order_type, Iterable):
21
+ order_type = (order_type,)
22
+
23
+ self._order_type: list[OrderType] = [self.__cast_to_OrderType(x) for x in order_type]
24
+
25
+ def __cast_to_OrderType(self, _value: Any) -> Iterable[OrderType]:
26
+ if isinstance(_value, OrderType):
27
+ return _value
28
+
29
+ if isinstance(_value, str):
30
+ try:
31
+ return OrderType(_value)
32
+ except Exception:
33
+ pass
34
+ raise Exception(f"order_type param only can be 'ASC' or 'DESC' string or '{OrderType.__name__}' enum")
35
+
36
+ def alias_children_resolver[Tclause](self, clause_info: ClauseInfo[Tclause]):
37
+ return None
38
+
39
+ @override
40
+ @property
41
+ def query(self) -> str:
42
+ assert len(self.all_clauses) == len(self._order_type)
43
+
44
+ query: list[str] = []
45
+ for index, x in enumerate(self.all_clauses):
46
+ query.append(f"{x.query} {self._order_type[index].value}")
47
+ return f"{self.ORDER} {", ".join(query)}"
@@ -3,6 +3,7 @@ from typing import override, Type, Callable, TYPE_CHECKING
3
3
  from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase
4
4
  from ormlambda.common.enums.join_type import JoinType
5
5
  from ormlambda.common.interfaces.IAggregate import IAggregate
6
+ import shapely as shp
6
7
 
7
8
  if TYPE_CHECKING:
8
9
  from ormlambda import Table
@@ -32,17 +33,20 @@ class Select[T: Type[Table]](DecompositionQueryBase[T]):
32
33
  # def alias_children_resolver[Tclause: Type[Table]](self, clause_info: ClauseInfo[Tclause]):
33
34
  # return f"{clause.table.__table_name__}_{name}"
34
35
 
36
+ # TODOL: see who to deal when we will have to add more mysql methods
35
37
  @override
36
38
  @property
37
39
  def query(self) -> str:
38
- cols:list[str] = []
40
+ cols: list[str] = []
39
41
  for x in self.all_clauses:
40
- cols.append(x.query)
42
+ if x.dtype is shp.Point:
43
+ cols.append(x.concat_with_alias(f"ST_AsText({self._table.__table_name__}.{x.column})"))
44
+ else:
45
+ cols.append(x.query)
41
46
 
42
- if isinstance(x._row_column,IAggregate) and x._row_column.has_foreign_keys:
47
+ if isinstance(x._row_column, IAggregate) and x._row_column.has_foreign_keys:
43
48
  self._fk_relationship.update(x._row_column.fk_relationship)
44
49
 
45
-
46
50
  col: str = ", ".join(cols)
47
51
  query: str = f"{self.CLAUSE} {col} FROM {self._table.__table_name__}"
48
52
  alias = ""
@@ -27,26 +27,20 @@ class UpdateQuery[T: Type[Table]](UpdateQueryBase[T, IRepositoryBase[MySQLConnec
27
27
  if not isinstance(dicc, dict):
28
28
  raise TypeError
29
29
 
30
- name_cols: list[str] = []
30
+ name_cols: list[Column] = []
31
31
 
32
32
  for col, value in dicc.items():
33
- if isinstance(col, str):
34
- string_col = col
35
- else:
36
- string_col = self._model.__properties_mapped__.get(col, None)
37
- if not string_col:
38
- raise KeyError(f"Class '{self._model.__name__}' has not {col} mapped.")
39
- if self.__is_valid__(string_col, value):
40
- name_cols.append(string_col)
41
- self._values.append(value)
42
-
43
- set_query: str = ",".join(["=".join([col, "%s"]) for col in name_cols])
33
+ col: Column = self._model.get_column(col, value)
34
+
35
+ if self.__is_valid__(col):
36
+ name_cols.append(col)
37
+ self._values.append(col.column_value_to_query)
38
+
39
+ set_query: str = ",".join(["=".join([col.column_name, col.placeholder]) for col in name_cols])
44
40
 
45
41
  self._query = f"{self.CLAUSE} {self._model.__table_name__} SET {set_query}"
42
+ self._values = tuple(self._values)
46
43
  return None
47
44
 
48
- def __is_valid__(self, col: str, value: Any) -> bool:
49
- instance_table: Table = self._model(**{col: value})
50
-
51
- column: Column = getattr(instance_table, f"_{col}")
52
- return not column.is_auto_generated
45
+ def __is_valid__(self, col: Column) -> bool:
46
+ return not col.is_auto_generated
@@ -0,0 +1,5 @@
1
+ from .max import Max as Max
2
+ from .min import Min as Min
3
+ from .concat import Concat as Concat
4
+ from ..clauses.group_by import GroupBy as GroupBy
5
+ from .sum import Sum as Sum
@@ -0,0 +1,39 @@
1
+ from ormlambda.common.interfaces import IAggregate
2
+ import typing as tp
3
+
4
+ from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase, ClauseInfo
5
+
6
+ if tp.TYPE_CHECKING:
7
+ from ormlambda import Table
8
+
9
+
10
+ class Sum[T: tp.Type[Table]](DecompositionQueryBase[T], IAggregate[T]):
11
+ NAME: str = "SUM"
12
+
13
+ @tp.overload
14
+ def __init__[T: tp.Type[Table]](self, table: T, column: tp.Callable[[T], tp.Any], *, alias: bool = True, alias_name: str = ...) -> None: ...
15
+
16
+ def __init__(
17
+ self,
18
+ table: T,
19
+ column: str | tp.Callable[[T], tuple],
20
+ *,
21
+ alias: bool = True,
22
+ alias_name: str = "sum",
23
+ ) -> None:
24
+ super().__init__(
25
+ table,
26
+ lambda_query=column,
27
+ alias=alias,
28
+ alias_name=alias_name,
29
+ )
30
+
31
+ def alias_children_resolver[Tclause: tp.Type[Table]](self, clause_info: ClauseInfo[Tclause]):
32
+ if isinstance(clause_info._row_column, IAggregate):
33
+ return clause_info._row_column.alias
34
+ return None
35
+
36
+ @property
37
+ def query(self) -> str:
38
+ col = ", ".join([x.query for x in self.all_clauses])
39
+ return f"{self.NAME}({col})"