ormlambda 2.11.1__tar.gz → 3.7.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 (153) hide show
  1. {ormlambda-2.11.1 → ormlambda-3.7.0}/PKG-INFO +132 -68
  2. {ormlambda-2.11.1 → ormlambda-3.7.0}/README.md +131 -67
  3. {ormlambda-2.11.1 → ormlambda-3.7.0}/pyproject.toml +2 -2
  4. ormlambda-3.7.0/src/ormlambda/__init__.py +22 -0
  5. ormlambda-3.7.0/src/ormlambda/caster/__init__.py +3 -0
  6. ormlambda-3.7.0/src/ormlambda/caster/base_caster.py +69 -0
  7. ormlambda-3.7.0/src/ormlambda/caster/caster.py +48 -0
  8. ormlambda-3.7.0/src/ormlambda/caster/interfaces/ICaster.py +26 -0
  9. ormlambda-3.7.0/src/ormlambda/caster/interfaces/__init__.py +1 -0
  10. ormlambda-3.7.0/src/ormlambda/common/__init__.py +1 -0
  11. ormlambda-3.7.0/src/ormlambda/common/abstract_classes/__init__.py +3 -0
  12. ormlambda-3.7.0/src/ormlambda/common/abstract_classes/decomposition_query.py +182 -0
  13. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/common/abstract_classes/non_query_base.py +1 -1
  14. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/common/enums/condition_types.py +2 -1
  15. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/common/enums/join_type.py +4 -1
  16. ormlambda-3.7.0/src/ormlambda/common/errors/__init__.py +21 -0
  17. ormlambda-3.7.0/src/ormlambda/common/global_checker.py +28 -0
  18. ormlambda-3.7.0/src/ormlambda/common/interfaces/ICustomAlias.py +7 -0
  19. ormlambda-3.7.0/src/ormlambda/common/interfaces/IDecompositionQuery.py +33 -0
  20. ormlambda-3.7.0/src/ormlambda/common/interfaces/IJoinSelector.py +21 -0
  21. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/common/interfaces/__init__.py +4 -6
  22. ormlambda-3.7.0/src/ormlambda/components/__init__.py +4 -0
  23. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/insert/abstract_insert.py +1 -1
  24. ormlambda-3.7.0/src/ormlambda/components/select/ISelect.py +17 -0
  25. ormlambda-3.7.0/src/ormlambda/components/select/__init__.py +1 -0
  26. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/update/abstract_update.py +4 -4
  27. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/upsert/abstract_upsert.py +1 -1
  28. ormlambda-3.7.0/src/ormlambda/databases/__init__.py +5 -0
  29. ormlambda-3.7.0/src/ormlambda/databases/my_sql/__init__.py +4 -0
  30. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/__init__.py +1 -0
  31. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/caster.py +38 -0
  32. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/read.py +39 -0
  33. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/types/__init__.py +8 -0
  34. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/types/bytes.py +31 -0
  35. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/types/datetime.py +34 -0
  36. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/types/float.py +31 -0
  37. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/types/int.py +31 -0
  38. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/types/iterable.py +31 -0
  39. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/types/none.py +30 -0
  40. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/types/point.py +43 -0
  41. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/types/string.py +31 -0
  42. ormlambda-3.7.0/src/ormlambda/databases/my_sql/caster/write.py +37 -0
  43. ormlambda-3.7.0/src/ormlambda/databases/my_sql/clauses/ST_AsText.py +36 -0
  44. ormlambda-3.7.0/src/ormlambda/databases/my_sql/clauses/ST_Contains.py +31 -0
  45. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/__init__.py +6 -4
  46. ormlambda-3.7.0/src/ormlambda/databases/my_sql/clauses/alias.py +34 -0
  47. ormlambda-3.7.0/src/ormlambda/databases/my_sql/clauses/count.py +43 -0
  48. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/create_database.py +3 -4
  49. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/delete.py +10 -10
  50. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/drop_database.py +3 -5
  51. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/drop_table.py +3 -3
  52. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/group_by.py +4 -7
  53. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/insert.py +33 -19
  54. ormlambda-3.7.0/src/ormlambda/databases/my_sql/clauses/joins.py +149 -0
  55. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/limit.py +1 -1
  56. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/offset.py +1 -1
  57. ormlambda-3.7.0/src/ormlambda/databases/my_sql/clauses/order.py +60 -0
  58. ormlambda-3.7.0/src/ormlambda/databases/my_sql/clauses/select.py +50 -0
  59. ormlambda-3.7.0/src/ormlambda/databases/my_sql/clauses/update.py +71 -0
  60. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/clauses/upsert.py +2 -2
  61. ormlambda-3.7.0/src/ormlambda/databases/my_sql/clauses/where.py +45 -0
  62. ormlambda-3.7.0/src/ormlambda/databases/my_sql/functions/concat.py +38 -0
  63. ormlambda-3.7.0/src/ormlambda/databases/my_sql/functions/max.py +43 -0
  64. ormlambda-3.7.0/src/ormlambda/databases/my_sql/functions/min.py +43 -0
  65. ormlambda-3.7.0/src/ormlambda/databases/my_sql/functions/sum.py +43 -0
  66. ormlambda-3.7.0/src/ormlambda/databases/my_sql/join_context.py +75 -0
  67. ormlambda-3.7.0/src/ormlambda/databases/my_sql/repository/__init__.py +1 -0
  68. {ormlambda-2.11.1/src/ormlambda/databases/my_sql → ormlambda-3.7.0/src/ormlambda/databases/my_sql/repository}/repository.py +104 -73
  69. ormlambda-3.7.0/src/ormlambda/databases/my_sql/statements.py +403 -0
  70. ormlambda-3.7.0/src/ormlambda/engine/template.py +47 -0
  71. ormlambda-3.7.0/src/ormlambda/model/base_model.py +37 -0
  72. ormlambda-3.7.0/src/ormlambda/repository/__init__.py +2 -0
  73. ormlambda-3.7.0/src/ormlambda/repository/base_repository.py +14 -0
  74. ormlambda-3.7.0/src/ormlambda/repository/interfaces/IDatabaseConnection.py +12 -0
  75. {ormlambda-2.11.1/src/ormlambda/common → ormlambda-3.7.0/src/ormlambda/repository}/interfaces/IRepositoryBase.py +6 -5
  76. ormlambda-3.7.0/src/ormlambda/repository/interfaces/__init__.py +2 -0
  77. ormlambda-3.7.0/src/ormlambda/sql/__init__.py +3 -0
  78. ormlambda-3.7.0/src/ormlambda/sql/clause_info/__init__.py +3 -0
  79. ormlambda-3.7.0/src/ormlambda/sql/clause_info/clause_info.py +434 -0
  80. ormlambda-3.7.0/src/ormlambda/sql/clause_info/clause_info_context.py +87 -0
  81. ormlambda-3.7.0/src/ormlambda/sql/clause_info/interface/IAggregate.py +10 -0
  82. ormlambda-3.7.0/src/ormlambda/sql/clause_info/interface/__init__.py +1 -0
  83. ormlambda-3.7.0/src/ormlambda/sql/column.py +126 -0
  84. ormlambda-3.7.0/src/ormlambda/sql/comparer.py +156 -0
  85. ormlambda-3.7.0/src/ormlambda/sql/foreign_key.py +115 -0
  86. ormlambda-3.7.0/src/ormlambda/sql/table/__init__.py +1 -0
  87. {ormlambda-2.11.1/src/ormlambda/utils → ormlambda-3.7.0/src/ormlambda/sql/table}/fields.py +6 -5
  88. {ormlambda-2.11.1/src/ormlambda/utils → ormlambda-3.7.0/src/ormlambda/sql/table}/table_constructor.py +43 -91
  89. ormlambda-3.7.0/src/ormlambda/sql/types.py +25 -0
  90. ormlambda-3.7.0/src/ormlambda/statements/__init__.py +2 -0
  91. ormlambda-3.7.0/src/ormlambda/statements/base_statement.py +129 -0
  92. ormlambda-3.7.0/src/ormlambda/statements/interfaces/IStatements.py +309 -0
  93. ormlambda-3.7.0/src/ormlambda/statements/interfaces/__init__.py +1 -0
  94. ormlambda-3.7.0/src/ormlambda/statements/types.py +51 -0
  95. ormlambda-3.7.0/src/ormlambda/utils/__init__.py +1 -0
  96. ormlambda-3.7.0/src/ormlambda/utils/module_tree/__init__.py +1 -0
  97. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/utils/module_tree/dynamic_module.py +20 -14
  98. ormlambda-2.11.1/src/ormlambda/__init__.py +0 -20
  99. ormlambda-2.11.1/src/ormlambda/common/__init__.py +0 -1
  100. ormlambda-2.11.1/src/ormlambda/common/abstract_classes/__init__.py +0 -3
  101. ormlambda-2.11.1/src/ormlambda/common/abstract_classes/abstract_model.py +0 -115
  102. ormlambda-2.11.1/src/ormlambda/common/abstract_classes/decomposition_query.py +0 -380
  103. ormlambda-2.11.1/src/ormlambda/common/errors/__init__.py +0 -8
  104. ormlambda-2.11.1/src/ormlambda/common/interfaces/IAggregate.py +0 -10
  105. ormlambda-2.11.1/src/ormlambda/common/interfaces/ICustomAlias.py +0 -4
  106. ormlambda-2.11.1/src/ormlambda/common/interfaces/IDecompositionQuery.py +0 -58
  107. ormlambda-2.11.1/src/ormlambda/common/interfaces/IStatements.py +0 -348
  108. ormlambda-2.11.1/src/ormlambda/components/where/__init__.py +0 -1
  109. ormlambda-2.11.1/src/ormlambda/components/where/abstract_where.py +0 -15
  110. ormlambda-2.11.1/src/ormlambda/databases/my_sql/__init__.py +0 -2
  111. ormlambda-2.11.1/src/ormlambda/databases/my_sql/clauses/alias.py +0 -31
  112. ormlambda-2.11.1/src/ormlambda/databases/my_sql/clauses/count.py +0 -39
  113. ormlambda-2.11.1/src/ormlambda/databases/my_sql/clauses/joins.py +0 -142
  114. ormlambda-2.11.1/src/ormlambda/databases/my_sql/clauses/order.py +0 -47
  115. ormlambda-2.11.1/src/ormlambda/databases/my_sql/clauses/select.py +0 -61
  116. ormlambda-2.11.1/src/ormlambda/databases/my_sql/clauses/update.py +0 -46
  117. ormlambda-2.11.1/src/ormlambda/databases/my_sql/clauses/where_condition.py +0 -222
  118. ormlambda-2.11.1/src/ormlambda/databases/my_sql/functions/concat.py +0 -41
  119. ormlambda-2.11.1/src/ormlambda/databases/my_sql/functions/max.py +0 -39
  120. ormlambda-2.11.1/src/ormlambda/databases/my_sql/functions/min.py +0 -39
  121. ormlambda-2.11.1/src/ormlambda/databases/my_sql/functions/sum.py +0 -39
  122. ormlambda-2.11.1/src/ormlambda/databases/my_sql/statements.py +0 -325
  123. ormlambda-2.11.1/src/ormlambda/model_base.py +0 -36
  124. ormlambda-2.11.1/src/ormlambda/utils/__init__.py +0 -3
  125. ormlambda-2.11.1/src/ormlambda/utils/column.py +0 -105
  126. ormlambda-2.11.1/src/ormlambda/utils/foreign_key.py +0 -81
  127. ormlambda-2.11.1/src/ormlambda/utils/lambda_disassembler/__init__.py +0 -4
  128. ormlambda-2.11.1/src/ormlambda/utils/lambda_disassembler/dis_types.py +0 -133
  129. ormlambda-2.11.1/src/ormlambda/utils/lambda_disassembler/disassembler.py +0 -69
  130. ormlambda-2.11.1/src/ormlambda/utils/lambda_disassembler/dtypes.py +0 -103
  131. ormlambda-2.11.1/src/ormlambda/utils/lambda_disassembler/name_of.py +0 -41
  132. ormlambda-2.11.1/src/ormlambda/utils/lambda_disassembler/nested_element.py +0 -44
  133. ormlambda-2.11.1/src/ormlambda/utils/lambda_disassembler/tree_instruction.py +0 -145
  134. {ormlambda-2.11.1 → ormlambda-3.7.0}/LICENSE +0 -0
  135. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/common/abstract_classes/query_base.py +0 -0
  136. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/common/enums/__init__.py +0 -0
  137. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/common/interfaces/INonQueryCommand.py +0 -0
  138. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/common/interfaces/IQueryCommand.py +0 -0
  139. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/delete/IDelete.py +0 -0
  140. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/delete/__init__.py +0 -0
  141. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/delete/abstract_delete.py +0 -0
  142. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/insert/IInsert.py +0 -0
  143. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/insert/__init__.py +0 -0
  144. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/update/IUpdate.py +0 -0
  145. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/update/__init__.py +0 -0
  146. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/upsert/IUpsert.py +0 -0
  147. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/components/upsert/__init__.py +0 -0
  148. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/databases/my_sql/functions/__init__.py +0 -0
  149. {ormlambda-2.11.1/src/ormlambda/components → ormlambda-3.7.0/src/ormlambda/engine}/__init__.py +0 -0
  150. {ormlambda-2.11.1/src/ormlambda/databases → ormlambda-3.7.0/src/ormlambda/model}/__init__.py +0 -0
  151. {ormlambda-2.11.1/src/ormlambda/utils → ormlambda-3.7.0/src/ormlambda/sql}/dtypes.py +0 -0
  152. {ormlambda-2.11.1/src/ormlambda/utils/module_tree → ormlambda-3.7.0/src/ormlambda/sql/interfaces}/__init__.py +0 -0
  153. {ormlambda-2.11.1 → ormlambda-3.7.0}/src/ormlambda/utils/module_tree/dfs_traversal.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ormlambda
3
- Version: 2.11.1
3
+ Version: 3.7.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
@@ -9,6 +9,7 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.12
10
10
  Requires-Dist: fluent-validation (==4.3.1)
11
11
  Requires-Dist: mysql-connector-python (>=9.0.0,<10.0.0)
12
+ Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
12
13
  Requires-Dist: shapely (>=2.0.6,<3.0.0)
13
14
  Description-Content-Type: text/markdown
14
15
 
@@ -36,9 +37,17 @@ database = MySQLRepository(user=USERNAME, password=PASSWORD, database="sakila",
36
37
 
37
38
  ## Select all columns
38
39
  ```python
39
- from models.address import AddressModel
40
+ from ormlambda import ORM
41
+ from ormlambda.databases.my_sql import MySQLRepository
42
+
43
+ from models.address import Address
44
+ from config import config_dict
45
+
46
+ db = MySQLRepository(**config_dict)
47
+
48
+ AddressModel = ORM(Address,db)
40
49
 
41
- result = AddressModel(database).select()
50
+ result = AddressModel.select()
42
51
  ```
43
52
  The `result` var will be of type `tuple[Address, ...]`
44
53
 
@@ -46,11 +55,13 @@ The `result` var will be of type `tuple[Address, ...]`
46
55
  Once the `AddressModel` class is created, we will not only be able to access all the information in that table, but also all the information in all the tables that have foreign keys related to it."
47
56
 
48
57
  ```python
49
- from ormlambda import ConditionType
50
- from models.address import AddressModel
58
+ from models.address import Address
51
59
 
60
+ db = MySQLRepository(**config_dict)
52
61
 
53
- result = AddressModel(database).where(lambda x: (x.City.Country, ConditionType.REGEXP, r"^[aA]")).select(
62
+ AddressModel = ORM(Address,db)
63
+
64
+ result = AddressModel.where(Address.City.Country.country.regex(r"^[aA]")).select(
54
65
  lambda address: (
55
66
  address,
56
67
  address.City,
@@ -64,31 +75,51 @@ If we were used `select_one` method, we retrieved `tuple[Address, City, Country]
64
75
 
65
76
  ## Filter by `where` condition
66
77
 
78
+ we can use only the Original Table to pass the variables like
67
79
  ```python
68
- result = AddressModel(database).where(lambda x: 10 <= x.address_id <= 30).select()
80
+ result = AddressModel.where(
81
+ [
82
+ Address.address_id >= 10,
83
+ Address.address_id <= 30,
84
+ ]
85
+ ).select()
69
86
  ```
87
+ Or by using a lambda function that returns an iterable for tables where the name is unusually long.
88
+
89
+ ```python
90
+ result = AddressModel.where(
91
+ lambda x: [
92
+ x.address_id >= 10,
93
+ x.address_id <= 30,
94
+ ]
95
+ ).select()
70
96
 
97
+ ```
71
98
  Additionally, we can filter by others tables. For example, we can return all addresses for each city where `country_id` = 87 (Spain)
72
99
 
73
100
  ```python
74
- result = AddressModel(database).where(lambda x: x.City.Country.country_id == 87).select()
101
+ result = AddressModel.where(Address.City.Country.country_id == 87).select()
75
102
  ```
76
103
 
77
104
  We can also return `Address`, `City` or `Country` if needed.
78
105
 
79
106
  ```python
80
- result = AddressModel(database).where(lambda x: x.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
107
+ result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
81
108
  ```
82
109
 
83
110
  ### Pass variables to the `where` method
84
- Since we generally work with lambda methods, I often have to work with `bytecode` to retrieve the name of the string variables. For this reason, it's imperative that we map these variables to replace them with the actual values.
85
-
86
111
  ```python
87
112
  LOWER = 10
88
113
  UPPER = 30
89
- AddressModel(database).where(lambda x: LOWER <= x.address_id <= UPPER, LOWER=LOWER, UPPER=UPPER).select()
114
+
115
+ AddressModel.where(
116
+ [
117
+ Address.address_id >= LOWER,
118
+ Address.address_id <= UPPER,
119
+ ]
120
+ ).select()
90
121
  ```
91
- That solution is somewhat `awkward` and not very clean, but it's necessary for automating queries.
122
+
92
123
 
93
124
  ## Writable methods INSERT, UPDATE, DELETE
94
125
  The easiest way to add or delete data in your database is by using its appropiate methods. You just need to instantiate an object with the data and pass it to the method
@@ -97,22 +128,21 @@ The easiest way to add or delete data in your database is by using its appropiat
97
128
  ```python
98
129
  address = Address(address_id=1, address="C/ ...", phone="XXXXXXXXX", postal_code="28026")
99
130
 
100
- AddressModel(database).insert(address)
131
+ AddressModel.insert(address)
101
132
  ```
102
133
 
103
134
  ### Update
104
-
105
135
  You can use either the properties of the same object or `str` values.
106
136
  ```python
107
137
 
108
- AddressModel(database).where(lambda x: x.address_id == 1).update(
138
+ AddressModel.where(lambda x: x.address_id == 1).update(
109
139
  {
110
140
  Address.phone: "YYYYYYYYY",
111
141
  Address.postal_code: "28030",
112
142
  }
113
143
  )
114
144
 
115
- AddressModel(database).where(lambda x: x.address_id == 1).update(
145
+ AddressModel.where(lambda x: x.address_id == 1).update(
116
146
  {
117
147
  "phone": "YYYYYYYYY",
118
148
  "postal_code": "28030",
@@ -122,7 +152,7 @@ AddressModel(database).where(lambda x: x.address_id == 1).update(
122
152
  ### Delete
123
153
 
124
154
  ```python
125
- AddressModel(database).where(lambda x: x.address_id == 1).delete()
155
+ AddressModel.where(lambda x: x.address_id == 1).delete()
126
156
  ```
127
157
 
128
158
 
@@ -139,67 +169,46 @@ The easiest way to map your tables is:
139
169
 
140
170
  ```python
141
171
  from datetime import datetime
142
-
143
172
  from ormlambda import (
144
- Column,
145
173
  Table,
146
- BaseModel,
174
+ Column,
147
175
  ForeignKey,
148
176
  )
149
- from ormlambda.common.interfaces import IStatements_two_generic, IRepositoryBase
150
-
151
177
 
152
178
  class Country(Table):
153
179
  __table_name__ = "country"
154
180
 
155
- country_id: int = Column[int](is_primary_key=True)
156
- country: str
157
- last_update: datetime
158
-
159
-
160
- class Address(Table):
161
- __table_name__ = "address"
162
-
163
- address_id: int = Column[int](is_primary_key=True)
164
- address: str
165
- address2: str
166
- district: str
167
- city_id: int
168
- postal_code: str
169
- phone: str
170
- location: str
171
- last_update: datetime = Column[datetime](is_auto_generated=True)
172
-
173
- City = ForeignKey["Address", City](__table_name__, City, lambda a, c: a.city_id == c.city_id)
181
+ country_id: Column[int] = Column(int, is_primary_key=True)
182
+ country: Column[str]
183
+ last_update: Column[datetime]
174
184
 
175
185
 
176
186
  class City(Table):
177
187
  __table_name__ = "city"
178
188
 
179
- city_id: int = Column[int](is_primary_key=True)
180
- city: str
181
- country_id: int
182
- last_update: datetime
183
-
184
- Country = ForeignKey["City", Country](__table_name__, Country, lambda ci, co: ci.country_id == co.country_id)
185
- ```
189
+ city_id: Column[int] = Column(int, is_primary_key=True)
190
+ city: Column[str]
191
+ country_id: Column[int]
192
+ last_update: Column[datetime]
186
193
 
187
- Once created, you need to create a Model for each Table
194
+ Country = ForeignKey["City", Country](Country, lambda ci, co: ci.country_id == co.country_id)
188
195
 
189
- ```python
190
- class CountryModel(BaseModel[Country]):
191
- def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
192
- return super().__new__(cls, Country, repository)
193
196
 
197
+ class Address(Table):
198
+ __table_name__ = "address"
194
199
 
195
- class AddressModel(BaseModel[Address]):
196
- def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
197
- return super().__new__(cls, Address, repository)
200
+ address_id: Column[int] = Column(int, is_primary_key=True)
201
+ address: Column[str]
202
+ address2: Column[str]
203
+ district: Column[str]
204
+ city_id: Column[int]
205
+ postal_code: Column[str]
206
+ phone: Column[str]
207
+ location: Column[str]
208
+ last_update: Column[datetime] = Column(datetime, is_auto_generated=True)
198
209
 
210
+ City = ForeignKey["Address", City](City, lambda a, c: a.city_id == c.city_id)
199
211
 
200
- class CityModel(BaseModel[City]):
201
- def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
202
- return super().__new__(cls, City, repository)
203
212
  ```
204
213
 
205
214
  # Creating complex queries with lambda
@@ -211,10 +220,10 @@ To retrieve all `Address` object where the fk reference to the `City` table, and
211
220
 
212
221
  ```python
213
222
  result = (
214
- AddressModel(database)
223
+ AddressModel
215
224
  .order(lambda a: a.address_id, order_type="DESC")
216
225
  .where(lambda x: x.City.Country.country_id >= 50)
217
- .select(lambda a: (a))
226
+ .select(Address)
218
227
  )
219
228
 
220
229
  ```
@@ -223,9 +232,9 @@ Also you can use `ConditionType` enum for `regular expressions` and get, for exa
223
232
 
224
233
  ```python
225
234
  address, city, country = (
226
- AddressModel(database)
227
- .order(lambda a: a.address_id, order_type="DESC")
228
- .where(lambda x: (x.City.Country, ConditionType.REGEXP, r"^[A]"))
235
+ AddressModel
236
+ .order(Address.address_id, order_type="DESC")
237
+ .where(Address.City.Country.country.regex(r"^[A]"))
229
238
  .limit(100)
230
239
  .select(
231
240
  lambda a: (
@@ -238,7 +247,6 @@ address, city, country = (
238
247
 
239
248
 
240
249
  for a in address:
241
-
242
250
  print(a.address_id)
243
251
 
244
252
  for c in city:
@@ -253,8 +261,7 @@ In the example above, we see that the `result` var returns a tuple of tuples. Ho
253
261
 
254
262
  ```python
255
263
  result = (
256
- a_model
257
- .where(lambda x: (x.City.Country, ConditionType.REGEXP, r"^[A]"))
264
+ AddressModel.where(Address.City.Country.country.regex(r"^[A]"))
258
265
  .limit(100)
259
266
  .select(
260
267
  lambda a: (
@@ -270,4 +277,61 @@ result = (
270
277
 
271
278
  with this approach, we will obtain a dictionary where the key will be the concatenation between the selected table name and the column name specified in the lambda function, to avoid overwritting data from tables that sharing column names.
272
279
 
280
+ # Other methods
273
281
 
282
+ ## max
283
+ ```python
284
+ res = AddressModel.max(Address.address_id, execute=True)
285
+ ```
286
+ ## min
287
+ ```python
288
+ res = AddressModel.min(Address.address_id, execute=True)
289
+ ```
290
+ ## sum
291
+ ```python
292
+ res = AddressModel.sum(Address.address_id, execute=True)
293
+ ```
294
+ ## count
295
+ ```python
296
+ res = AddressModel.count(Address.address_id, execute=True)
297
+ ```
298
+
299
+ ## Combine aggregation method
300
+ As shown in the previous examples, setting the `execute` attribute to `True` allows us to perform the corresponding query in a single line. However, if you're looking to improve efficiency, you can combine all of them into one query.
301
+ ```python
302
+ result = AddressModel.select_one(
303
+ lambda x: (
304
+ AddressModel.min(x.address_id),
305
+ AddressModel.max(x.address_id),
306
+ AddressModel.count(x.address_id),
307
+ ),flavour=dict
308
+ )
309
+ ```
310
+ Getting something like
311
+
312
+ ```python
313
+ # {
314
+ # "min": 1,
315
+ # "max": 605,
316
+ # "count": 603,
317
+ # }
318
+ ```
319
+
320
+ You also can use custom alias for each method
321
+
322
+ ```python
323
+ AddressModel.select_one(
324
+ lambda x: (
325
+ AddressModel.min(x.address_id),
326
+ AddressModel.max(x.address_id, alias="custom-max"),
327
+ AddressModel.count(x.address_id),
328
+ ),
329
+ flavour=dict,
330
+ )
331
+
332
+ # {
333
+ # "min": 1,
334
+ # "custom-max": 605,
335
+ # "count": 603,
336
+ # }
337
+ ```
@@ -22,9 +22,17 @@ database = MySQLRepository(user=USERNAME, password=PASSWORD, database="sakila",
22
22
 
23
23
  ## Select all columns
24
24
  ```python
25
- from models.address import AddressModel
25
+ from ormlambda import ORM
26
+ from ormlambda.databases.my_sql import MySQLRepository
27
+
28
+ from models.address import Address
29
+ from config import config_dict
30
+
31
+ db = MySQLRepository(**config_dict)
32
+
33
+ AddressModel = ORM(Address,db)
26
34
 
27
- result = AddressModel(database).select()
35
+ result = AddressModel.select()
28
36
  ```
29
37
  The `result` var will be of type `tuple[Address, ...]`
30
38
 
@@ -32,11 +40,13 @@ The `result` var will be of type `tuple[Address, ...]`
32
40
  Once the `AddressModel` class is created, we will not only be able to access all the information in that table, but also all the information in all the tables that have foreign keys related to it."
33
41
 
34
42
  ```python
35
- from ormlambda import ConditionType
36
- from models.address import AddressModel
43
+ from models.address import Address
37
44
 
45
+ db = MySQLRepository(**config_dict)
38
46
 
39
- result = AddressModel(database).where(lambda x: (x.City.Country, ConditionType.REGEXP, r"^[aA]")).select(
47
+ AddressModel = ORM(Address,db)
48
+
49
+ result = AddressModel.where(Address.City.Country.country.regex(r"^[aA]")).select(
40
50
  lambda address: (
41
51
  address,
42
52
  address.City,
@@ -50,31 +60,51 @@ If we were used `select_one` method, we retrieved `tuple[Address, City, Country]
50
60
 
51
61
  ## Filter by `where` condition
52
62
 
63
+ we can use only the Original Table to pass the variables like
53
64
  ```python
54
- result = AddressModel(database).where(lambda x: 10 <= x.address_id <= 30).select()
65
+ result = AddressModel.where(
66
+ [
67
+ Address.address_id >= 10,
68
+ Address.address_id <= 30,
69
+ ]
70
+ ).select()
55
71
  ```
72
+ Or by using a lambda function that returns an iterable for tables where the name is unusually long.
73
+
74
+ ```python
75
+ result = AddressModel.where(
76
+ lambda x: [
77
+ x.address_id >= 10,
78
+ x.address_id <= 30,
79
+ ]
80
+ ).select()
56
81
 
82
+ ```
57
83
  Additionally, we can filter by others tables. For example, we can return all addresses for each city where `country_id` = 87 (Spain)
58
84
 
59
85
  ```python
60
- result = AddressModel(database).where(lambda x: x.City.Country.country_id == 87).select()
86
+ result = AddressModel.where(Address.City.Country.country_id == 87).select()
61
87
  ```
62
88
 
63
89
  We can also return `Address`, `City` or `Country` if needed.
64
90
 
65
91
  ```python
66
- result = AddressModel(database).where(lambda x: x.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
92
+ result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
67
93
  ```
68
94
 
69
95
  ### Pass variables to the `where` method
70
- Since we generally work with lambda methods, I often have to work with `bytecode` to retrieve the name of the string variables. For this reason, it's imperative that we map these variables to replace them with the actual values.
71
-
72
96
  ```python
73
97
  LOWER = 10
74
98
  UPPER = 30
75
- AddressModel(database).where(lambda x: LOWER <= x.address_id <= UPPER, LOWER=LOWER, UPPER=UPPER).select()
99
+
100
+ AddressModel.where(
101
+ [
102
+ Address.address_id >= LOWER,
103
+ Address.address_id <= UPPER,
104
+ ]
105
+ ).select()
76
106
  ```
77
- That solution is somewhat `awkward` and not very clean, but it's necessary for automating queries.
107
+
78
108
 
79
109
  ## Writable methods INSERT, UPDATE, DELETE
80
110
  The easiest way to add or delete data in your database is by using its appropiate methods. You just need to instantiate an object with the data and pass it to the method
@@ -83,22 +113,21 @@ The easiest way to add or delete data in your database is by using its appropiat
83
113
  ```python
84
114
  address = Address(address_id=1, address="C/ ...", phone="XXXXXXXXX", postal_code="28026")
85
115
 
86
- AddressModel(database).insert(address)
116
+ AddressModel.insert(address)
87
117
  ```
88
118
 
89
119
  ### Update
90
-
91
120
  You can use either the properties of the same object or `str` values.
92
121
  ```python
93
122
 
94
- AddressModel(database).where(lambda x: x.address_id == 1).update(
123
+ AddressModel.where(lambda x: x.address_id == 1).update(
95
124
  {
96
125
  Address.phone: "YYYYYYYYY",
97
126
  Address.postal_code: "28030",
98
127
  }
99
128
  )
100
129
 
101
- AddressModel(database).where(lambda x: x.address_id == 1).update(
130
+ AddressModel.where(lambda x: x.address_id == 1).update(
102
131
  {
103
132
  "phone": "YYYYYYYYY",
104
133
  "postal_code": "28030",
@@ -108,7 +137,7 @@ AddressModel(database).where(lambda x: x.address_id == 1).update(
108
137
  ### Delete
109
138
 
110
139
  ```python
111
- AddressModel(database).where(lambda x: x.address_id == 1).delete()
140
+ AddressModel.where(lambda x: x.address_id == 1).delete()
112
141
  ```
113
142
 
114
143
 
@@ -125,67 +154,46 @@ The easiest way to map your tables is:
125
154
 
126
155
  ```python
127
156
  from datetime import datetime
128
-
129
157
  from ormlambda import (
130
- Column,
131
158
  Table,
132
- BaseModel,
159
+ Column,
133
160
  ForeignKey,
134
161
  )
135
- from ormlambda.common.interfaces import IStatements_two_generic, IRepositoryBase
136
-
137
162
 
138
163
  class Country(Table):
139
164
  __table_name__ = "country"
140
165
 
141
- country_id: int = Column[int](is_primary_key=True)
142
- country: str
143
- last_update: datetime
144
-
145
-
146
- class Address(Table):
147
- __table_name__ = "address"
148
-
149
- address_id: int = Column[int](is_primary_key=True)
150
- address: str
151
- address2: str
152
- district: str
153
- city_id: int
154
- postal_code: str
155
- phone: str
156
- location: str
157
- last_update: datetime = Column[datetime](is_auto_generated=True)
158
-
159
- City = ForeignKey["Address", City](__table_name__, City, lambda a, c: a.city_id == c.city_id)
166
+ country_id: Column[int] = Column(int, is_primary_key=True)
167
+ country: Column[str]
168
+ last_update: Column[datetime]
160
169
 
161
170
 
162
171
  class City(Table):
163
172
  __table_name__ = "city"
164
173
 
165
- city_id: int = Column[int](is_primary_key=True)
166
- city: str
167
- country_id: int
168
- last_update: datetime
169
-
170
- Country = ForeignKey["City", Country](__table_name__, Country, lambda ci, co: ci.country_id == co.country_id)
171
- ```
174
+ city_id: Column[int] = Column(int, is_primary_key=True)
175
+ city: Column[str]
176
+ country_id: Column[int]
177
+ last_update: Column[datetime]
172
178
 
173
- Once created, you need to create a Model for each Table
179
+ Country = ForeignKey["City", Country](Country, lambda ci, co: ci.country_id == co.country_id)
174
180
 
175
- ```python
176
- class CountryModel(BaseModel[Country]):
177
- def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
178
- return super().__new__(cls, Country, repository)
179
181
 
182
+ class Address(Table):
183
+ __table_name__ = "address"
180
184
 
181
- class AddressModel(BaseModel[Address]):
182
- def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
183
- return super().__new__(cls, Address, repository)
185
+ address_id: Column[int] = Column(int, is_primary_key=True)
186
+ address: Column[str]
187
+ address2: Column[str]
188
+ district: Column[str]
189
+ city_id: Column[int]
190
+ postal_code: Column[str]
191
+ phone: Column[str]
192
+ location: Column[str]
193
+ last_update: Column[datetime] = Column(datetime, is_auto_generated=True)
184
194
 
195
+ City = ForeignKey["Address", City](City, lambda a, c: a.city_id == c.city_id)
185
196
 
186
- class CityModel(BaseModel[City]):
187
- def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
188
- return super().__new__(cls, City, repository)
189
197
  ```
190
198
 
191
199
  # Creating complex queries with lambda
@@ -197,10 +205,10 @@ To retrieve all `Address` object where the fk reference to the `City` table, and
197
205
 
198
206
  ```python
199
207
  result = (
200
- AddressModel(database)
208
+ AddressModel
201
209
  .order(lambda a: a.address_id, order_type="DESC")
202
210
  .where(lambda x: x.City.Country.country_id >= 50)
203
- .select(lambda a: (a))
211
+ .select(Address)
204
212
  )
205
213
 
206
214
  ```
@@ -209,9 +217,9 @@ Also you can use `ConditionType` enum for `regular expressions` and get, for exa
209
217
 
210
218
  ```python
211
219
  address, city, country = (
212
- AddressModel(database)
213
- .order(lambda a: a.address_id, order_type="DESC")
214
- .where(lambda x: (x.City.Country, ConditionType.REGEXP, r"^[A]"))
220
+ AddressModel
221
+ .order(Address.address_id, order_type="DESC")
222
+ .where(Address.City.Country.country.regex(r"^[A]"))
215
223
  .limit(100)
216
224
  .select(
217
225
  lambda a: (
@@ -224,7 +232,6 @@ address, city, country = (
224
232
 
225
233
 
226
234
  for a in address:
227
-
228
235
  print(a.address_id)
229
236
 
230
237
  for c in city:
@@ -239,8 +246,7 @@ In the example above, we see that the `result` var returns a tuple of tuples. Ho
239
246
 
240
247
  ```python
241
248
  result = (
242
- a_model
243
- .where(lambda x: (x.City.Country, ConditionType.REGEXP, r"^[A]"))
249
+ AddressModel.where(Address.City.Country.country.regex(r"^[A]"))
244
250
  .limit(100)
245
251
  .select(
246
252
  lambda a: (
@@ -256,3 +262,61 @@ result = (
256
262
 
257
263
  with this approach, we will obtain a dictionary where the key will be the concatenation between the selected table name and the column name specified in the lambda function, to avoid overwritting data from tables that sharing column names.
258
264
 
265
+ # Other methods
266
+
267
+ ## max
268
+ ```python
269
+ res = AddressModel.max(Address.address_id, execute=True)
270
+ ```
271
+ ## min
272
+ ```python
273
+ res = AddressModel.min(Address.address_id, execute=True)
274
+ ```
275
+ ## sum
276
+ ```python
277
+ res = AddressModel.sum(Address.address_id, execute=True)
278
+ ```
279
+ ## count
280
+ ```python
281
+ res = AddressModel.count(Address.address_id, execute=True)
282
+ ```
283
+
284
+ ## Combine aggregation method
285
+ As shown in the previous examples, setting the `execute` attribute to `True` allows us to perform the corresponding query in a single line. However, if you're looking to improve efficiency, you can combine all of them into one query.
286
+ ```python
287
+ result = AddressModel.select_one(
288
+ lambda x: (
289
+ AddressModel.min(x.address_id),
290
+ AddressModel.max(x.address_id),
291
+ AddressModel.count(x.address_id),
292
+ ),flavour=dict
293
+ )
294
+ ```
295
+ Getting something like
296
+
297
+ ```python
298
+ # {
299
+ # "min": 1,
300
+ # "max": 605,
301
+ # "count": 603,
302
+ # }
303
+ ```
304
+
305
+ You also can use custom alias for each method
306
+
307
+ ```python
308
+ AddressModel.select_one(
309
+ lambda x: (
310
+ AddressModel.min(x.address_id),
311
+ AddressModel.max(x.address_id, alias="custom-max"),
312
+ AddressModel.count(x.address_id),
313
+ ),
314
+ flavour=dict,
315
+ )
316
+
317
+ # {
318
+ # "min": 1,
319
+ # "custom-max": 605,
320
+ # "count": 603,
321
+ # }
322
+ ```
@@ -3,7 +3,7 @@ line-length = 320
3
3
 
4
4
  [tool.poetry]
5
5
  name = "ormlambda"
6
- version = "2.11.1"
6
+ version = "3.7.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"
@@ -13,11 +13,11 @@ python = "^3.12"
13
13
  mysql-connector-python= "^9.0.0"
14
14
  fluent-validation = "4.3.1"
15
15
  shapely = "^2.0.6"
16
+ python-dotenv = "^1.0.1"
16
17
 
17
18
  [tool.poetry.group.test.dependencies]
18
19
  pandas = "^2.2.2"
19
20
  ruff = "^0.4.5"
20
- python-decouple = "^3.8"
21
21
  parameterized = "^0.9.0"
22
22
 
23
23