ormlambda 4.0.0__tar.gz → 4.0.4__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.4}/PKG-INFO +33 -54
  2. {ormlambda-4.0.0 → ormlambda-4.0.4}/README.md +32 -53
  3. {ormlambda-4.0.0 → ormlambda-4.0.4}/pyproject.toml +1 -1
  4. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/repository/response.py +9 -1
  5. ormlambda-4.0.4/src/ormlambda/statements/base_statement.py +85 -0
  6. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/statements/interfaces/IStatements.py +4 -4
  7. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/statements/statements.py +3 -6
  8. ormlambda-4.0.0/src/ormlambda/statements/base_statement.py +0 -90
  9. {ormlambda-4.0.0 → ormlambda-4.0.4}/AUTHORS +0 -0
  10. {ormlambda-4.0.0 → ormlambda-4.0.4}/LICENSE +0 -0
  11. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/__init__.py +0 -0
  12. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/caster/__init__.py +0 -0
  13. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/caster/base_caster.py +0 -0
  14. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/caster/caster.py +0 -0
  15. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/caster/interfaces/ICaster.py +0 -0
  16. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/caster/interfaces/__init__.py +0 -0
  17. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/__init__.py +0 -0
  18. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/abstract_classes/__init__.py +0 -0
  19. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/abstract_classes/non_query_base.py +0 -0
  20. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/enums/__init__.py +0 -0
  21. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/enums/condition_types.py +0 -0
  22. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/enums/join_type.py +0 -0
  23. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/enums/order_type.py +0 -0
  24. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/errors/__init__.py +0 -0
  25. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/global_checker.py +0 -0
  26. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/interfaces/IJoinSelector.py +0 -0
  27. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/interfaces/INonQueryCommand.py +0 -0
  28. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/interfaces/IQueryCommand.py +0 -0
  29. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/common/interfaces/__init__.py +0 -0
  30. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/__init__.py +0 -0
  31. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/default/__init__.py +0 -0
  32. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/default/base.py +0 -0
  33. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/__init__.py +0 -0
  34. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/base.py +0 -0
  35. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/__init__.py +0 -0
  36. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/caster.py +0 -0
  37. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/__init__.py +0 -0
  38. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/boolean.py +0 -0
  39. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/bytes.py +0 -0
  40. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/date.py +0 -0
  41. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/datetime.py +0 -0
  42. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/decimal.py +0 -0
  43. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/float.py +0 -0
  44. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/int.py +0 -0
  45. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/iterable.py +0 -0
  46. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/json.py +0 -0
  47. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/none.py +0 -0
  48. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/point.py +0 -0
  49. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/caster/types/string.py +0 -0
  50. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/clauses/ST_AsText.py +0 -0
  51. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/clauses/ST_Contains.py +0 -0
  52. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/clauses/__init__.py +0 -0
  53. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/mysqlconnector.py +0 -0
  54. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/repository/__init__.py +0 -0
  55. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/repository/pool_types.py +0 -0
  56. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/repository/repository.py +0 -0
  57. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/mysql/types.py +0 -0
  58. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/sqlite/__init__.py +0 -0
  59. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/sqlite/base.py +0 -0
  60. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/dialects/sqlite/pysqlite.py +0 -0
  61. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/engine/__init__.py +0 -0
  62. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/engine/base.py +0 -0
  63. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/engine/create.py +0 -0
  64. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/engine/url.py +0 -0
  65. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/engine/utils.py +0 -0
  66. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/env.py +0 -0
  67. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/errors.py +0 -0
  68. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/model/__init__.py +0 -0
  69. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/model/base_model.py +0 -0
  70. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/repository/__init__.py +0 -0
  71. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/repository/base_repository.py +0 -0
  72. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/repository/interfaces/IDatabaseConnection.py +0 -0
  73. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/repository/interfaces/IRepositoryBase.py +0 -0
  74. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/repository/interfaces/__init__.py +0 -0
  75. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/__init__.py +0 -0
  76. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clause_info/__init__.py +0 -0
  77. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clause_info/clause_info.py +0 -0
  78. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clause_info/interface/IAggregate.py +0 -0
  79. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clause_info/interface/IClauseInfo.py +0 -0
  80. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clause_info/interface/__init__.py +0 -0
  81. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/__init__.py +0 -0
  82. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/alias.py +0 -0
  83. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/count.py +0 -0
  84. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/delete.py +0 -0
  85. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/group_by.py +0 -0
  86. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/having.py +0 -0
  87. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/insert.py +0 -0
  88. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/interfaces/IDelete.py +0 -0
  89. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/interfaces/IInsert.py +0 -0
  90. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/interfaces/IUpdate.py +0 -0
  91. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/interfaces/IUpsert.py +0 -0
  92. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/interfaces/__init__.py +0 -0
  93. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/join/__init__.py +0 -0
  94. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/join/join_context.py +0 -0
  95. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/joins.py +0 -0
  96. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/limit.py +0 -0
  97. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/offset.py +0 -0
  98. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/order.py +0 -0
  99. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/select.py +0 -0
  100. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/update.py +0 -0
  101. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/upsert.py +0 -0
  102. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/clauses/where.py +0 -0
  103. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/column/__init__.py +0 -0
  104. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/column/column.py +0 -0
  105. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/column/column_proxy.py +0 -0
  106. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/column_table_proxy.py +0 -0
  107. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/comparer.py +0 -0
  108. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/compiler.py +0 -0
  109. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/context/__init__.py +0 -0
  110. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/ddl.py +0 -0
  111. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/elements.py +0 -0
  112. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/foreign_key.py +0 -0
  113. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/functions/__init__.py +0 -0
  114. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/functions/concat.py +0 -0
  115. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/functions/max.py +0 -0
  116. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/functions/min.py +0 -0
  117. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/functions/sum.py +0 -0
  118. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/interfaces/__init__.py +0 -0
  119. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/sqltypes.py +0 -0
  120. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/table/__init__.py +0 -0
  121. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/table/fields.py +0 -0
  122. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/table/table.py +0 -0
  123. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/table/table_constructor.py +0 -0
  124. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/table/table_proxy.py +0 -0
  125. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/type_api.py +0 -0
  126. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/types.py +0 -0
  127. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/sql/visitors.py +0 -0
  128. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/statements/__init__.py +0 -0
  129. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/statements/interfaces/__init__.py +0 -0
  130. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/statements/query_builder.py +0 -0
  131. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/statements/types.py +0 -0
  132. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/types/__init__.py +0 -0
  133. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/types/metadata.py +0 -0
  134. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/util/__init__.py +0 -0
  135. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/util/langhelpers.py +0 -0
  136. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/util/module_tree/__init__.py +0 -0
  137. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/util/module_tree/dfs_traversal.py +0 -0
  138. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/util/module_tree/dynamic_module.py +0 -0
  139. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/util/preloaded.py +0 -0
  140. {ormlambda-4.0.0 → ormlambda-4.0.4}/src/ormlambda/util/typing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ormlambda
3
- Version: 4.0.0
3
+ Version: 4.0.4
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
@@ -90,16 +90,7 @@ If we were used `select_one` method, we retrieved `tuple[Address, City, Country]
90
90
 
91
91
  ## Filter by `where` condition
92
92
 
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.
93
+ We can use lambda function that returns an iterable to pass the iterable like.
103
94
 
104
95
  ```python
105
96
  result = AddressModel.where(
@@ -119,7 +110,7 @@ result = AddressModel.where(Address.City.Country.country_id == 87).select()
119
110
  We can also return `Address`, `City` or `Country` if needed.
120
111
 
121
112
  ```python
122
- result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
113
+ result = AddressModel.where(lambda x: x.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
123
114
  ```
124
115
 
125
116
  ### Pass variables to the `where` method
@@ -127,10 +118,10 @@ result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda
127
118
  LOWER = 10
128
119
  UPPER = 30
129
120
 
130
- AddressModel.where(
121
+ AddressModel.where(lambda x:
131
122
  [
132
- Address.address_id >= LOWER,
133
- Address.address_id <= UPPER,
123
+ x.address_id >= LOWER,
124
+ x.address_id <= UPPER,
134
125
  ]
135
126
  ).select()
136
127
  ```
@@ -238,7 +229,7 @@ result = (
238
229
  AddressModel
239
230
  .order(lambda a: a.address_id, order_type="DESC")
240
231
  .where(lambda x: x.City.Country.country_id >= 50)
241
- .select(Address)
232
+ .select()
242
233
  )
243
234
 
244
235
  ```
@@ -246,13 +237,12 @@ Also you can use `ConditionType` enum for `regular expressions` and get, for exa
246
237
 
247
238
 
248
239
  ```python
249
- address, city, country = (
240
+ response = (
250
241
  AddressModel
251
- .order(Address.address_id, order_type="DESC")
252
- .where(Address.City.Country.country.regex(r"^[A]"))
242
+ .order(lambda x: x.address_id, order_type="DESC")
243
+ .where(lambda x: x.City.Country.country.regex(r"^[A]"))
253
244
  .limit(100)
254
- .select(
255
- lambda a: (
245
+ .select(lambda a: (
256
246
  a,
257
247
  a.City,
258
248
  a.City.Country,
@@ -261,13 +251,9 @@ address, city, country = (
261
251
  )
262
252
 
263
253
 
264
- for a in address:
254
+ for a,c,co in response:
265
255
  print(a.address_id)
266
-
267
- for c in city:
268
256
  print(c.city_id)
269
-
270
- for co in country:
271
257
  print(co.country)
272
258
  ```
273
259
 
@@ -276,10 +262,9 @@ In the example above, we see that the `result` var returns a tuple of tuples. Ho
276
262
 
277
263
  ```python
278
264
  result = (
279
- AddressModel.where(Address.City.Country.country.regex(r"^[A]"))
265
+ AddressModel.where(lambda x: x.City.Country.country.regex(r"^[A]"))
280
266
  .limit(100)
281
- .select(
282
- lambda a: (
267
+ .select(lambda a: (
283
268
  a.address_id,
284
269
  a.City.city_id,
285
270
  a.City.Country.country_id,
@@ -318,28 +303,23 @@ The `concat` method allows you to concatenate multiple columns or values into a
318
303
  ### Usage
319
304
 
320
305
  ```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
- )
306
+ response = (
307
+ ORM(Address, db)
308
+ .where(lambda x: x.City.Country.country.regex(r"^Spain"))
309
+ .first(
310
+ lambda x: (
311
+ x.address,
312
+ x.City.city,
313
+ Concat(("Address: ", x.address, " - city: ", x.City.city, " - country: ", x.City.Country.country)),
314
+ ),
315
+ flavour=dict,
316
+ )
317
+ )
338
318
 
339
319
  {
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",
320
+ "address": "939 Probolinggo Loop",
321
+ "city": "A Coruña (La Coruña)",
322
+ "concat": "Address: 939 Probolinggo Loop - city: A Coruña (La Coruña) - country: Spain",
343
323
  }
344
324
  ```
345
325
  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 +370,7 @@ res = (
390
370
  .select(lambda x:
391
371
  (
392
372
  x.district,
393
- Count(x.address),
373
+ Count(x.address,alias="count"),
394
374
  ),
395
375
  flavour=Response,
396
376
  )
@@ -442,11 +422,10 @@ print(select.city)
442
422
  print(select.country)
443
423
  ```
444
424
 
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.
425
+ ## Aggregation method
426
+ You can also use `aggregation methods` to create more informative queries.
447
427
  ```python
448
- result = AddressModel.select_one(
449
- lambda x: (
428
+ result = AddressModel.select_one(lambda x: (
450
429
  Min(x.address_id),
451
430
  Max(x.address_id),
452
431
  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.4"
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"
@@ -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](
@@ -1,90 +0,0 @@
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
- from ormlambda import util
8
-
9
- from ormlambda.common.errors import AggregateFunctionError
10
- from ormlambda.sql.clause_info import IAggregate
11
-
12
-
13
- if TYPE_CHECKING:
14
- from ormlambda.engine.base import Engine
15
- from ormlambda.sql.clauses import Select
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
- tbl_dicc: dict[Type[Table], list[dict[str, Any]]] = self._create_cluster(response_sql)
33
-
34
- first_table = list(tbl_dicc)[0]
35
- tuple_response = []
36
- # it not depend of flavour attr
37
- n_attrs = len(tbl_dicc[first_table])
38
- for i in range(n_attrs):
39
- new_instance = []
40
- for table in tbl_dicc:
41
- attrs = tbl_dicc[table][i]
42
- new_instance.append(table(**attrs))
43
- tuple_response.append(tuple(new_instance))
44
- return tuple(tuple_response)
45
-
46
- def _create_cluster(self, response_sql: ResponseType) -> dict[Type[Table], list[dict[str, Any]]]:
47
- # We'll create a default list of dicts *once* we know how many rows are in _response_sql
48
- row_count = len(response_sql)
49
-
50
- def make_list_of_dicts() -> list[dict[str, Any]]:
51
- return [{} for _ in range(row_count)]
52
-
53
- table_attr_dict = defaultdict(make_list_of_dicts)
54
-
55
- for i, dicc_cols in enumerate(response_sql):
56
- for clause in self._select.columns:
57
- # if col is None or not hasattr(table, col):
58
- if isinstance(clause, IAggregate):
59
- raise AggregateFunctionError(clause)
60
-
61
- table = clause.table
62
-
63
- table_attr_dict[table][i][clause.column_name] = dicc_cols[clause.alias]
64
- # Convert back to a normal dict if you like (defaultdict is a dict subclass).
65
- return dict(table_attr_dict)
66
-
67
- @util.preload_module("ormlambda.sql.column")
68
- def response(self, **kwargs) -> TFlavour[T, ...]:
69
- ColumnProxy = util.preloaded.sql_column.ColumnProxy
70
-
71
- if not self.flavour:
72
- return self._return_model()
73
-
74
- result = self._return_flavour(self.flavour, self._select, **kwargs)
75
- if issubclass(self.flavour, tuple) and len(self._select.used_columns()) == 1 and isinstance(self._select.used_columns()[0], ColumnProxy):
76
- return tuple([x[0] for x in result])
77
- return result
78
-
79
- def _return_flavour[TValue](self, flavour: Type[TValue], select, **kwargs) -> tuple[TValue]:
80
- return self.engine.repository.read_sql(self.query, flavour=flavour, select=select, **kwargs)
81
-
82
- def _return_model(self) -> tuple[tuple[T]]:
83
- response_sql = self.engine.repository.read_sql(self.query, flavour=dict, select=self._select) # store all columns of the SQL query
84
- if response_sql and isinstance(response_sql, Iterable):
85
- response = self.cluster(response_sql)
86
- if response and len(response[0]) == 1:
87
- return tuple([x[0] for x in response])
88
- return response
89
-
90
- return response_sql
File without changes
File without changes