ormlambda 4.0.0__tar.gz → 4.0.5__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 (140) hide show
  1. {ormlambda-4.0.0 → ormlambda-4.0.5}/PKG-INFO +35 -55
  2. {ormlambda-4.0.0 → ormlambda-4.0.5}/README.md +32 -53
  3. {ormlambda-4.0.0 → ormlambda-4.0.5}/pyproject.toml +1 -1
  4. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/__init__.py +11 -4
  5. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/default/base.py +3 -2
  6. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/base.py +4 -1
  7. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/engine/base.py +15 -2
  8. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/engine/create.py +6 -1
  9. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/repository/base_repository.py +4 -0
  10. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/repository/response.py +9 -1
  11. ormlambda-4.0.5/src/ormlambda/statements/base_statement.py +85 -0
  12. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/statements/interfaces/IStatements.py +4 -4
  13. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/statements/statements.py +3 -6
  14. ormlambda-4.0.0/src/ormlambda/statements/base_statement.py +0 -90
  15. {ormlambda-4.0.0 → ormlambda-4.0.5}/AUTHORS +0 -0
  16. {ormlambda-4.0.0 → ormlambda-4.0.5}/LICENSE +0 -0
  17. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/__init__.py +0 -0
  18. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/caster/__init__.py +0 -0
  19. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/caster/base_caster.py +0 -0
  20. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/caster/caster.py +0 -0
  21. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/caster/interfaces/ICaster.py +0 -0
  22. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/caster/interfaces/__init__.py +0 -0
  23. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/__init__.py +0 -0
  24. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/abstract_classes/__init__.py +0 -0
  25. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/abstract_classes/non_query_base.py +0 -0
  26. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/enums/__init__.py +0 -0
  27. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/enums/condition_types.py +0 -0
  28. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/enums/join_type.py +0 -0
  29. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/enums/order_type.py +0 -0
  30. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/errors/__init__.py +0 -0
  31. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/global_checker.py +0 -0
  32. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/interfaces/IJoinSelector.py +0 -0
  33. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/interfaces/INonQueryCommand.py +0 -0
  34. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/interfaces/IQueryCommand.py +0 -0
  35. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/common/interfaces/__init__.py +0 -0
  36. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/default/__init__.py +0 -0
  37. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/__init__.py +0 -0
  38. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/__init__.py +0 -0
  39. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/caster.py +0 -0
  40. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/__init__.py +0 -0
  41. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/boolean.py +0 -0
  42. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/bytes.py +0 -0
  43. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/date.py +0 -0
  44. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/datetime.py +0 -0
  45. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/decimal.py +0 -0
  46. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/float.py +0 -0
  47. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/int.py +0 -0
  48. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/iterable.py +0 -0
  49. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/json.py +0 -0
  50. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/none.py +0 -0
  51. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/point.py +0 -0
  52. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/caster/types/string.py +0 -0
  53. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/clauses/ST_AsText.py +0 -0
  54. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/clauses/ST_Contains.py +0 -0
  55. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/clauses/__init__.py +0 -0
  56. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/mysqlconnector.py +0 -0
  57. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/repository/__init__.py +0 -0
  58. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/repository/pool_types.py +0 -0
  59. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/repository/repository.py +0 -0
  60. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/mysql/types.py +0 -0
  61. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/sqlite/__init__.py +0 -0
  62. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/sqlite/base.py +0 -0
  63. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/dialects/sqlite/pysqlite.py +0 -0
  64. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/engine/__init__.py +0 -0
  65. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/engine/url.py +0 -0
  66. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/engine/utils.py +0 -0
  67. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/env.py +0 -0
  68. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/errors.py +0 -0
  69. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/model/__init__.py +0 -0
  70. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/model/base_model.py +0 -0
  71. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/repository/__init__.py +0 -0
  72. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/repository/interfaces/IDatabaseConnection.py +0 -0
  73. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/repository/interfaces/IRepositoryBase.py +0 -0
  74. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/repository/interfaces/__init__.py +0 -0
  75. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/__init__.py +0 -0
  76. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clause_info/__init__.py +0 -0
  77. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clause_info/clause_info.py +0 -0
  78. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clause_info/interface/IAggregate.py +0 -0
  79. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clause_info/interface/IClauseInfo.py +0 -0
  80. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clause_info/interface/__init__.py +0 -0
  81. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/__init__.py +0 -0
  82. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/alias.py +0 -0
  83. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/count.py +0 -0
  84. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/delete.py +0 -0
  85. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/group_by.py +0 -0
  86. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/having.py +0 -0
  87. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/insert.py +0 -0
  88. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/interfaces/IDelete.py +0 -0
  89. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/interfaces/IInsert.py +0 -0
  90. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/interfaces/IUpdate.py +0 -0
  91. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/interfaces/IUpsert.py +0 -0
  92. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/interfaces/__init__.py +0 -0
  93. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/join/__init__.py +0 -0
  94. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/join/join_context.py +0 -0
  95. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/joins.py +0 -0
  96. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/limit.py +0 -0
  97. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/offset.py +0 -0
  98. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/order.py +0 -0
  99. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/select.py +0 -0
  100. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/update.py +0 -0
  101. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/upsert.py +0 -0
  102. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/clauses/where.py +0 -0
  103. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/column/__init__.py +0 -0
  104. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/column/column.py +0 -0
  105. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/column/column_proxy.py +0 -0
  106. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/column_table_proxy.py +0 -0
  107. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/comparer.py +0 -0
  108. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/compiler.py +0 -0
  109. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/context/__init__.py +0 -0
  110. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/ddl.py +0 -0
  111. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/elements.py +0 -0
  112. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/foreign_key.py +0 -0
  113. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/functions/__init__.py +0 -0
  114. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/functions/concat.py +0 -0
  115. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/functions/max.py +0 -0
  116. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/functions/min.py +0 -0
  117. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/functions/sum.py +0 -0
  118. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/interfaces/__init__.py +0 -0
  119. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/sqltypes.py +0 -0
  120. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/table/__init__.py +0 -0
  121. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/table/fields.py +0 -0
  122. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/table/table.py +0 -0
  123. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/table/table_constructor.py +0 -0
  124. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/table/table_proxy.py +0 -0
  125. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/type_api.py +0 -0
  126. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/types.py +0 -0
  127. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/sql/visitors.py +0 -0
  128. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/statements/__init__.py +0 -0
  129. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/statements/interfaces/__init__.py +0 -0
  130. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/statements/query_builder.py +0 -0
  131. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/statements/types.py +0 -0
  132. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/types/__init__.py +0 -0
  133. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/types/metadata.py +0 -0
  134. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/util/__init__.py +0 -0
  135. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/util/langhelpers.py +0 -0
  136. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/util/module_tree/__init__.py +0 -0
  137. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/util/module_tree/dfs_traversal.py +0 -0
  138. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/util/module_tree/dynamic_module.py +0 -0
  139. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/util/preloaded.py +0 -0
  140. {ormlambda-4.0.0 → ormlambda-4.0.5}/src/ormlambda/util/typing.py +0 -0
@@ -1,12 +1,13 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: ormlambda
3
- Version: 4.0.0
3
+ Version: 4.0.5
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
+ Classifier: Programming Language :: Python :: 3.13
10
11
  Requires-Dist: mysql-connector-python (>=9.0.0,<10.0.0)
11
12
  Requires-Dist: shapely (>=2.0.6,<3.0.0)
12
13
  Description-Content-Type: text/markdown
@@ -90,16 +91,7 @@ If we were used `select_one` method, we retrieved `tuple[Address, City, Country]
90
91
 
91
92
  ## Filter by `where` condition
92
93
 
93
- we can use only the Original Table to pass the variables like
94
- ```python
95
- result = AddressModel.where(
96
- [
97
- Address.address_id >= 10,
98
- Address.address_id <= 30,
99
- ]
100
- ).select()
101
- ```
102
- Or by using a lambda function that returns an iterable for tables where the name is unusually long.
94
+ We can use lambda function that returns an iterable to pass the iterable like.
103
95
 
104
96
  ```python
105
97
  result = AddressModel.where(
@@ -119,7 +111,7 @@ result = AddressModel.where(Address.City.Country.country_id == 87).select()
119
111
  We can also return `Address`, `City` or `Country` if needed.
120
112
 
121
113
  ```python
122
- result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
114
+ result = AddressModel.where(lambda x: x.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
123
115
  ```
124
116
 
125
117
  ### Pass variables to the `where` method
@@ -127,10 +119,10 @@ result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda
127
119
  LOWER = 10
128
120
  UPPER = 30
129
121
 
130
- AddressModel.where(
122
+ AddressModel.where(lambda x:
131
123
  [
132
- Address.address_id >= LOWER,
133
- Address.address_id <= UPPER,
124
+ x.address_id >= LOWER,
125
+ x.address_id <= UPPER,
134
126
  ]
135
127
  ).select()
136
128
  ```
@@ -238,7 +230,7 @@ result = (
238
230
  AddressModel
239
231
  .order(lambda a: a.address_id, order_type="DESC")
240
232
  .where(lambda x: x.City.Country.country_id >= 50)
241
- .select(Address)
233
+ .select()
242
234
  )
243
235
 
244
236
  ```
@@ -246,13 +238,12 @@ Also you can use `ConditionType` enum for `regular expressions` and get, for exa
246
238
 
247
239
 
248
240
  ```python
249
- address, city, country = (
241
+ response = (
250
242
  AddressModel
251
- .order(Address.address_id, order_type="DESC")
252
- .where(Address.City.Country.country.regex(r"^[A]"))
243
+ .order(lambda x: x.address_id, order_type="DESC")
244
+ .where(lambda x: x.City.Country.country.regex(r"^[A]"))
253
245
  .limit(100)
254
- .select(
255
- lambda a: (
246
+ .select(lambda a: (
256
247
  a,
257
248
  a.City,
258
249
  a.City.Country,
@@ -261,13 +252,9 @@ address, city, country = (
261
252
  )
262
253
 
263
254
 
264
- for a in address:
255
+ for a,c,co in response:
265
256
  print(a.address_id)
266
-
267
- for c in city:
268
257
  print(c.city_id)
269
-
270
- for co in country:
271
258
  print(co.country)
272
259
  ```
273
260
 
@@ -276,10 +263,9 @@ In the example above, we see that the `result` var returns a tuple of tuples. Ho
276
263
 
277
264
  ```python
278
265
  result = (
279
- AddressModel.where(Address.City.Country.country.regex(r"^[A]"))
266
+ AddressModel.where(lambda x: x.City.Country.country.regex(r"^[A]"))
280
267
  .limit(100)
281
- .select(
282
- lambda a: (
268
+ .select(lambda a: (
283
269
  a.address_id,
284
270
  a.City.city_id,
285
271
  a.City.Country.country_id,
@@ -318,28 +304,23 @@ The `concat` method allows you to concatenate multiple columns or values into a
318
304
  ### Usage
319
305
 
320
306
  ```python
321
- response = ORM(Address, db).where(Address.City.Country.country.regex(r"^Spain")).first(
322
- (
323
- Address.address,
324
- Address.City.city,
325
- Concat(lambda x:
326
- (
327
- "Address: ",
328
- x.address,
329
- " - city: ",
330
- x.City.city,
331
- " - country: ",
332
- x.City.Country.country,
333
- )
334
- ),
335
- ),
336
- flavour=dict,
337
- )
307
+ response = (
308
+ ORM(Address, db)
309
+ .where(lambda x: x.City.Country.country.regex(r"^Spain"))
310
+ .first(
311
+ lambda x: (
312
+ x.address,
313
+ x.City.city,
314
+ Concat(("Address: ", x.address, " - city: ", x.City.city, " - country: ", x.City.Country.country)),
315
+ ),
316
+ flavour=dict,
317
+ )
318
+ )
338
319
 
339
320
  {
340
- "address_address": "939 Probolinggo Loop",
341
- "city_city": "A Coruña (La Coruña)",
342
- "CONCAT": "Address: 939 Probolinggo Loop - city: A Coruña (La Coruña) - country: Spain",
321
+ "address": "939 Probolinggo Loop",
322
+ "city": "A Coruña (La Coruña)",
323
+ "concat": "Address: 939 Probolinggo Loop - city: A Coruña (La Coruña) - country: Spain",
343
324
  }
344
325
  ```
345
326
  As you can see in the response, the result is a dictionary where the keys are a combination of the table name and the column name. This is done to avoid collisions with columns from other tables that might have the same name.
@@ -390,7 +371,7 @@ res = (
390
371
  .select(lambda x:
391
372
  (
392
373
  x.district,
393
- Count(x.address),
374
+ Count(x.address,alias="count"),
394
375
  ),
395
376
  flavour=Response,
396
377
  )
@@ -442,11 +423,10 @@ print(select.city)
442
423
  print(select.country)
443
424
  ```
444
425
 
445
- ## Combine aggregation method
446
- 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.
426
+ ## Aggregation method
427
+ You can also use `aggregation methods` to create more informative queries.
447
428
  ```python
448
- result = AddressModel.select_one(
449
- lambda x: (
429
+ result = AddressModel.select_one(lambda x: (
450
430
  Min(x.address_id),
451
431
  Max(x.address_id),
452
432
  Count(x.address_id),
@@ -77,16 +77,7 @@ If we were used `select_one` method, we retrieved `tuple[Address, City, Country]
77
77
 
78
78
  ## Filter by `where` condition
79
79
 
80
- we can use only the Original Table to pass the variables like
81
- ```python
82
- result = AddressModel.where(
83
- [
84
- Address.address_id >= 10,
85
- Address.address_id <= 30,
86
- ]
87
- ).select()
88
- ```
89
- Or by using a lambda function that returns an iterable for tables where the name is unusually long.
80
+ We can use lambda function that returns an iterable to pass the iterable like.
90
81
 
91
82
  ```python
92
83
  result = AddressModel.where(
@@ -106,7 +97,7 @@ result = AddressModel.where(Address.City.Country.country_id == 87).select()
106
97
  We can also return `Address`, `City` or `Country` if needed.
107
98
 
108
99
  ```python
109
- result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
100
+ result = AddressModel.where(lambda x: x.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
110
101
  ```
111
102
 
112
103
  ### Pass variables to the `where` method
@@ -114,10 +105,10 @@ result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda
114
105
  LOWER = 10
115
106
  UPPER = 30
116
107
 
117
- AddressModel.where(
108
+ AddressModel.where(lambda x:
118
109
  [
119
- Address.address_id >= LOWER,
120
- Address.address_id <= UPPER,
110
+ x.address_id >= LOWER,
111
+ x.address_id <= UPPER,
121
112
  ]
122
113
  ).select()
123
114
  ```
@@ -225,7 +216,7 @@ result = (
225
216
  AddressModel
226
217
  .order(lambda a: a.address_id, order_type="DESC")
227
218
  .where(lambda x: x.City.Country.country_id >= 50)
228
- .select(Address)
219
+ .select()
229
220
  )
230
221
 
231
222
  ```
@@ -233,13 +224,12 @@ Also you can use `ConditionType` enum for `regular expressions` and get, for exa
233
224
 
234
225
 
235
226
  ```python
236
- address, city, country = (
227
+ response = (
237
228
  AddressModel
238
- .order(Address.address_id, order_type="DESC")
239
- .where(Address.City.Country.country.regex(r"^[A]"))
229
+ .order(lambda x: x.address_id, order_type="DESC")
230
+ .where(lambda x: x.City.Country.country.regex(r"^[A]"))
240
231
  .limit(100)
241
- .select(
242
- lambda a: (
232
+ .select(lambda a: (
243
233
  a,
244
234
  a.City,
245
235
  a.City.Country,
@@ -248,13 +238,9 @@ address, city, country = (
248
238
  )
249
239
 
250
240
 
251
- for a in address:
241
+ for a,c,co in response:
252
242
  print(a.address_id)
253
-
254
- for c in city:
255
243
  print(c.city_id)
256
-
257
- for co in country:
258
244
  print(co.country)
259
245
  ```
260
246
 
@@ -263,10 +249,9 @@ In the example above, we see that the `result` var returns a tuple of tuples. Ho
263
249
 
264
250
  ```python
265
251
  result = (
266
- AddressModel.where(Address.City.Country.country.regex(r"^[A]"))
252
+ AddressModel.where(lambda x: x.City.Country.country.regex(r"^[A]"))
267
253
  .limit(100)
268
- .select(
269
- lambda a: (
254
+ .select(lambda a: (
270
255
  a.address_id,
271
256
  a.City.city_id,
272
257
  a.City.Country.country_id,
@@ -305,28 +290,23 @@ The `concat` method allows you to concatenate multiple columns or values into a
305
290
  ### Usage
306
291
 
307
292
  ```python
308
- response = ORM(Address, db).where(Address.City.Country.country.regex(r"^Spain")).first(
309
- (
310
- Address.address,
311
- Address.City.city,
312
- Concat(lambda x:
313
- (
314
- "Address: ",
315
- x.address,
316
- " - city: ",
317
- x.City.city,
318
- " - country: ",
319
- x.City.Country.country,
320
- )
321
- ),
322
- ),
323
- flavour=dict,
324
- )
293
+ response = (
294
+ ORM(Address, db)
295
+ .where(lambda x: x.City.Country.country.regex(r"^Spain"))
296
+ .first(
297
+ lambda x: (
298
+ x.address,
299
+ x.City.city,
300
+ Concat(("Address: ", x.address, " - city: ", x.City.city, " - country: ", x.City.Country.country)),
301
+ ),
302
+ flavour=dict,
303
+ )
304
+ )
325
305
 
326
306
  {
327
- "address_address": "939 Probolinggo Loop",
328
- "city_city": "A Coruña (La Coruña)",
329
- "CONCAT": "Address: 939 Probolinggo Loop - city: A Coruña (La Coruña) - country: Spain",
307
+ "address": "939 Probolinggo Loop",
308
+ "city": "A Coruña (La Coruña)",
309
+ "concat": "Address: 939 Probolinggo Loop - city: A Coruña (La Coruña) - country: Spain",
330
310
  }
331
311
  ```
332
312
  As you can see in the response, the result is a dictionary where the keys are a combination of the table name and the column name. This is done to avoid collisions with columns from other tables that might have the same name.
@@ -377,7 +357,7 @@ res = (
377
357
  .select(lambda x:
378
358
  (
379
359
  x.district,
380
- Count(x.address),
360
+ Count(x.address,alias="count"),
381
361
  ),
382
362
  flavour=Response,
383
363
  )
@@ -429,11 +409,10 @@ print(select.city)
429
409
  print(select.country)
430
410
  ```
431
411
 
432
- ## Combine aggregation method
433
- 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.
412
+ ## Aggregation method
413
+ You can also use `aggregation methods` to create more informative queries.
434
414
  ```python
435
- result = AddressModel.select_one(
436
- lambda x: (
415
+ result = AddressModel.select_one(lambda x: (
437
416
  Min(x.address_id),
438
417
  Max(x.address_id),
439
418
  Count(x.address_id),
@@ -3,7 +3,7 @@ line-length = 320
3
3
 
4
4
  [tool.poetry]
5
5
  name = "ormlambda"
6
- version = "4.0.0"
6
+ version = "4.0.5"
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"
@@ -3,13 +3,14 @@ from typing import Callable, Optional, Type, TYPE_CHECKING, ClassVar
3
3
  import abc
4
4
  from ormlambda import util
5
5
  import importlib
6
+ from ormlambda import BaseRepository
6
7
 
7
8
 
8
9
  if TYPE_CHECKING:
10
+ from ormlambda import URL
9
11
  from ormlambda.caster.caster import Caster
10
12
  from ormlambda.repository.interfaces.IRepositoryBase import DBAPIConnection
11
13
  from ormlambda.sql.types import DDLCompiler, SQLCompiler, TypeCompiler
12
- from ormlambda import BaseRepository
13
14
 
14
15
 
15
16
  class Dialect(abc.ABC):
@@ -57,15 +58,21 @@ class Dialect(abc.ABC):
57
58
  type_compiler_instance: ClassVar[TypeCompiler]
58
59
  """The instance of the type compiler class used by the dialect."""
59
60
 
60
- repository_cls: ClassVar[Type[BaseRepository]]
61
- """The repository class used by the dialect."""
62
-
63
61
  caster: ClassVar[Type[Caster]]
64
62
 
65
63
  @classmethod
66
64
  def get_dialect_cls(cls) -> Type[Dialect]:
67
65
  return cls
68
66
 
67
+ @classmethod
68
+ @abc.abstractmethod
69
+ def get_pool_class(cls, url: URL) -> Type[BaseRepository]: ...
70
+
71
+ @abc.abstractmethod
72
+ def get_dialect_pool_class(self, url: str) -> None:
73
+ """Validates an identifier name, raising an exception if invalid"""
74
+ ...
75
+
69
76
  @classmethod
70
77
  @abc.abstractmethod
71
78
  def import_dbapi(cls) -> DBAPIConnection:
@@ -2,7 +2,6 @@ from ormlambda.dialects import Dialect
2
2
  from ormlambda.sql import compiler
3
3
  from typing import Optional, Any
4
4
  from types import ModuleType
5
- from ormlambda import BaseRepository
6
5
 
7
6
 
8
7
  class DefaultDialect(Dialect):
@@ -11,7 +10,6 @@ class DefaultDialect(Dialect):
11
10
  statement_compiler = compiler.SQLCompiler
12
11
  ddl_compiler = compiler.DDLCompiler
13
12
  type_compiler_cls = compiler.GenericTypeCompiler
14
- repository_cls = BaseRepository
15
13
  default_paramstyle = "named"
16
14
 
17
15
  def __init__(
@@ -37,3 +35,6 @@ class DefaultDialect(Dialect):
37
35
  self.type_compiler_instance = self.type_compiler = tt_callable(self)
38
36
 
39
37
  super().__init__(**kwargs)
38
+
39
+ def get_dialect_pool_class(self, url):
40
+ return self.get_pool_class(url)
@@ -627,7 +627,6 @@ class MySQLDialect(default.DefaultDialect):
627
627
  statement_compiler = MySQLCompiler
628
628
  ddl_compiler = MySQLDDLCompiler
629
629
  type_compiler_cls = MySQLTypeCompiler
630
- repository_cls = MySQLRepository
631
630
  caster = MySQLCaster
632
631
 
633
632
  def __init__(self, **kwargs):
@@ -638,3 +637,7 @@ class MySQLDialect(default.DefaultDialect):
638
637
  from mysql import connector
639
638
 
640
639
  return connector
640
+
641
+ @classmethod
642
+ def get_pool_class(cls, url):
643
+ return MySQLRepository
@@ -3,6 +3,7 @@ from pathlib import Path
3
3
  from typing import TYPE_CHECKING, BinaryIO, Literal, Optional, TextIO
4
4
  from ormlambda.engine import url
5
5
  from ormlambda.sql.ddl import CreateSchema, DropSchema, CreateBackup
6
+ from ormlambda import BaseRepository
6
7
 
7
8
  if TYPE_CHECKING:
8
9
  from ormlambda.dialects import Dialect
@@ -11,10 +12,10 @@ type TypeExists = Literal["fail", "replace", "append"]
11
12
 
12
13
 
13
14
  class Engine:
14
- def __init__(self, dialect: Dialect, url: url.URL):
15
+ def __init__(self, repository: BaseRepository, dialect: Dialect, url: url.URL):
16
+ self.repository = repository
15
17
  self.dialect = dialect
16
18
  self.url = url
17
- self.repository = self.dialect.repository_cls(url, dialect=dialect)
18
19
 
19
20
  def __repr__(self):
20
21
  return f"{Engine.__name__}: {self.url}"
@@ -78,3 +79,15 @@ class Engine:
78
79
  )
79
80
  .string
80
81
  )
82
+
83
+ @property
84
+ def engine(self) -> Engine:
85
+ return self
86
+
87
+ @property
88
+ def driver(self) -> str:
89
+ return self.dialect.driver
90
+
91
+ @property
92
+ def name(self) -> str:
93
+ return self.dialect.name
@@ -18,4 +18,9 @@ def create_engine(url: URL | str, **kwargs: Any) -> base.Engine:
18
18
  dialect_args["dbapi"] = dialect_cls.import_dbapi()
19
19
 
20
20
  dialect = dialect_cls(**dialect_args)
21
- return base.Engine(dialect, u)
21
+
22
+ repositoryclass = dialect.get_dialect_pool_class(u)
23
+
24
+ repository_args = {"dialect": dialect, **kwargs}
25
+ repository = repositoryclass(u, **repository_args)
26
+ return base.Engine(repository, dialect, u)
@@ -42,3 +42,7 @@ class BaseRepository[TPool](IRepositoryBase):
42
42
 
43
43
  @abc.abstractmethod
44
44
  def get_connection[TCnx](self) -> Generator[TCnx, None, None]: ...
45
+
46
+ @property
47
+ def pool(self) -> TPool:
48
+ return self._pool
@@ -67,7 +67,15 @@ class Response[TFlavour, *Ts]:
67
67
 
68
68
  def _tuple(**kwargs) -> list[tuple[*Ts]]:
69
69
  nonlocal data
70
- return data
70
+ result = []
71
+ for value in data:
72
+ if len(value) ==1:
73
+ result.append(value[0])
74
+ continue
75
+ result.append(value)
76
+
77
+
78
+ return result
71
79
 
72
80
  def _set(**kwargs) -> list[set]:
73
81
  nonlocal data
@@ -0,0 +1,85 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Type, Iterable, Literal, TYPE_CHECKING
3
+ from collections import defaultdict
4
+
5
+
6
+ from ormlambda import Table
7
+
8
+ from ormlambda.common.errors import AggregateFunctionError
9
+ from ormlambda.sql.clause_info import IAggregate
10
+
11
+
12
+ if TYPE_CHECKING:
13
+ from ormlambda.engine.base import Engine
14
+ from ormlambda.sql.clauses import Select
15
+ from ormlambda import ColumnProxy
16
+
17
+
18
+ ORDER_QUERIES = Literal["select", "join", "where", "order", "with", "group by", "limit", "offset"]
19
+
20
+
21
+ type ResponseType = Iterable[dict[str, Any]]
22
+
23
+
24
+ class ClusterResponse[T, TFlavour]:
25
+ def __init__(self, select: Select[T], engine: Engine, flavour: TFlavour, query: str) -> None:
26
+ self._select: Select[T] = select
27
+ self.engine = engine
28
+ self.flavour = flavour
29
+ self.query = query
30
+
31
+ def cluster(self, response_sql: ResponseType) -> tuple[dict[Type[Table], tuple[Table, ...]]]:
32
+ # We'll create a default list of dicts *once* we know how many rows are in _response_sql
33
+
34
+ tables: dict[Table, list[ColumnProxy]] = defaultdict(list)
35
+ for clause in self._select.columns:
36
+ if isinstance(clause, IAggregate):
37
+ raise AggregateFunctionError(clause)
38
+
39
+ tables[clause.table].append(clause)
40
+
41
+ res = []
42
+ for dicc_cols in response_sql:
43
+ converted_row = []
44
+ for table, columns in tables.items():
45
+ dicc = {}
46
+ for col in columns:
47
+ if not hasattr(col, "column_name"):
48
+ pass
49
+ dicc[col.column_name] = dicc_cols[col.alias]
50
+ converted_row.append(table(**dicc))
51
+ res.append(tuple(converted_row))
52
+
53
+ tuple_response = tuple(res)
54
+
55
+ if not tuple_response:
56
+ return tuple_response
57
+
58
+ if len(tuple_response) == 1:
59
+ return tuple_response[0]
60
+
61
+ if len(tuple_response[0]) == 1:
62
+ return tuple([x[0] for x in tuple_response])
63
+ return tuple_response
64
+
65
+ def cluster_data(self, **kwargs) -> TFlavour[T, ...]:
66
+ if not self.flavour:
67
+ return self._return_model()
68
+
69
+ return self._return_flavour(self.flavour, **kwargs)
70
+
71
+ def _return_flavour[TValue](self, flavour: Type[TValue], **kwargs) -> tuple[TValue]:
72
+ return self.engine.repository.read_sql(
73
+ query=self.query,
74
+ flavour=flavour,
75
+ select=self._select,
76
+ **kwargs,
77
+ )
78
+
79
+ def _return_model(self) -> tuple[tuple[T]]:
80
+ response_sql = self._return_flavour(flavour=dict)
81
+
82
+ if response_sql and isinstance(response_sql, Iterable):
83
+ return self.cluster(response_sql)
84
+
85
+ return response_sql
@@ -214,9 +214,9 @@ class IStatements[T: Table](Element):
214
214
 
215
215
  # region deal with flavours
216
216
  @overload
217
- def select[TFlavour](self, selector: Callable[[T], tuple[tuple]] = ..., *, flavour: Type[TFlavour], **kwargs) -> tuple[TFlavour, ...]: ...
218
- @overload
219
217
  def select[*TRes](self, selector: Callable[[T], tuple[*TRes]] = ..., *, flavour: Type[tuple], **kwargs) -> tuple[tuple[*TRes]]: ...
218
+ @overload
219
+ def select[TFlavour](self, selector: Callable[[T], tuple] = ..., *, flavour: Type[TFlavour], **kwargs) -> tuple[TFlavour, ...]: ...
220
220
 
221
221
  # endregion
222
222
 
@@ -244,7 +244,7 @@ class IStatements[T: Table](Element):
244
244
  @overload
245
245
  def select_one[*TRes](self, selector: Callable[[T], tuple[*TRes]], *, flavour: Type[list], by: JoinType = ..., alias: Optional[AliasType[ColumnType]] = ..., avoid_duplicates: bool = ...) -> tuple[*TRes]: ...
246
246
  @overload
247
- def select_one[TFlavour, *TRes](self, selector: Callable[[T], tuple[T, *TRes]], *, flavour: Type[TFlavour], by: JoinType = ..., alias: Optional[AliasType[ColumnType]] = ..., avoid_duplicates: bool = ...) -> TFlavour[*TRes]: ...
247
+ def select_one[TFlavour, *TRes](self, selector: Callable[[T], tuple[*TRes]], *, flavour: Type[TFlavour], by: JoinType = ..., alias: Optional[AliasType[ColumnType]] = ..., avoid_duplicates: bool = ...) -> TFlavour[*TRes]: ...
248
248
 
249
249
  @abstractmethod
250
250
  def select_one(
@@ -271,7 +271,7 @@ class IStatements[T: Table](Element):
271
271
  @overload
272
272
  def first[*TRes](self, selector: Callable[[T], tuple[*TRes]], *, flavour: Type[list], by: JoinType = ..., alias: Optional[AliasType[ColumnType]] = ..., avoid_duplicates: bool = ...) -> tuple[*TRes]: ...
273
273
  @overload
274
- def first[TFlavour, *TRes](self, selector: Callable[[T], tuple[T, *TRes]], *, flavour: Type[TFlavour], by: JoinType = ..., alias: Optional[AliasType[ColumnType]] = ..., avoid_duplicates: bool = ...) -> TFlavour[*TRes]: ...
274
+ def first[TFlavour, *TRes](self, selector: Callable[[T], tuple[*TRes]], *, flavour: Type[TFlavour], by: JoinType = ..., alias: Optional[AliasType[ColumnType]] = ..., avoid_duplicates: bool = ...) -> TFlavour[*TRes]: ...
275
275
 
276
276
  @abstractmethod
277
277
  def first(
@@ -277,7 +277,7 @@ class Statements[T: Table](IStatements[T]):
277
277
  self._query_builder.by = by
278
278
  self._query: str = self._query_builder.query(self._dialect)
279
279
 
280
- return ClusterResponse(select, self._engine, flavour, self._query).response()
280
+ return ClusterResponse(select, self._engine, flavour, self._query).cluster_data()
281
281
 
282
282
  @override
283
283
  def select_one[TValue, TFlavour, *Ts](
@@ -301,11 +301,8 @@ class Statements[T: Table](IStatements[T]):
301
301
  # select columns from different tables using a join query
302
302
  # FIXME [x]: before it was if len(response) == 1 and len(response[0]) == 1: return response[0][0]
303
303
  if len(response) == 1:
304
- if isinstance(response[0], Iterable) and len(response[0]) == 1:
305
- return response[0][0]
306
- else:
307
- return response[0]
308
- return tuple([res[0] for res in response])
304
+ return response[0]
305
+ return response
309
306
 
310
307
  @override
311
308
  def first[TValue, TFlavour, *Ts](