amsdal 0.5.23__cp311-cp311-macosx_10_9_universal2.whl

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.

Potentially problematic release.


This version of amsdal might be problematic. Click here for more details.

Files changed (252) hide show
  1. amsdal/Third-Party Materials - AMSDAL Dependencies - License Notices.md +1334 -0
  2. amsdal/__about__.py +4 -0
  3. amsdal/__about__.pyi +1 -0
  4. amsdal/__init__.py +23 -0
  5. amsdal/__init__.pyi +9 -0
  6. amsdal/__migrations__/0000_initial.py +36 -0
  7. amsdal/__migrations__/0001_create_class_file.py +61 -0
  8. amsdal/__migrations__/0002_create_class_file.py +109 -0
  9. amsdal/__migrations__/0003_update_class_file.py +91 -0
  10. amsdal/__migrations__/0004_update_class_file.py +45 -0
  11. amsdal/cloud/__init__.cpython-311-darwin.so +0 -0
  12. amsdal/cloud/__init__.pyi +0 -0
  13. amsdal/cloud/client.cpython-311-darwin.so +0 -0
  14. amsdal/cloud/client.pyi +57 -0
  15. amsdal/cloud/constants.cpython-311-darwin.so +0 -0
  16. amsdal/cloud/constants.pyi +13 -0
  17. amsdal/cloud/enums.cpython-311-darwin.so +0 -0
  18. amsdal/cloud/enums.pyi +68 -0
  19. amsdal/cloud/models/__init__.cpython-311-darwin.so +0 -0
  20. amsdal/cloud/models/__init__.pyi +0 -0
  21. amsdal/cloud/models/base.cpython-311-darwin.so +0 -0
  22. amsdal/cloud/models/base.pyi +247 -0
  23. amsdal/cloud/services/__init__.cpython-311-darwin.so +0 -0
  24. amsdal/cloud/services/__init__.pyi +0 -0
  25. amsdal/cloud/services/actions/__init__.cpython-311-darwin.so +0 -0
  26. amsdal/cloud/services/actions/__init__.pyi +0 -0
  27. amsdal/cloud/services/actions/add_allowlist_ip.cpython-311-darwin.so +0 -0
  28. amsdal/cloud/services/actions/add_allowlist_ip.pyi +19 -0
  29. amsdal/cloud/services/actions/add_basic_auth.cpython-311-darwin.so +0 -0
  30. amsdal/cloud/services/actions/add_basic_auth.pyi +21 -0
  31. amsdal/cloud/services/actions/add_dependency.cpython-311-darwin.so +0 -0
  32. amsdal/cloud/services/actions/add_dependency.pyi +19 -0
  33. amsdal/cloud/services/actions/add_secret.cpython-311-darwin.so +0 -0
  34. amsdal/cloud/services/actions/add_secret.pyi +20 -0
  35. amsdal/cloud/services/actions/base.cpython-311-darwin.so +0 -0
  36. amsdal/cloud/services/actions/base.pyi +122 -0
  37. amsdal/cloud/services/actions/create_deploy.cpython-311-darwin.so +0 -0
  38. amsdal/cloud/services/actions/create_deploy.pyi +41 -0
  39. amsdal/cloud/services/actions/create_env.cpython-311-darwin.so +0 -0
  40. amsdal/cloud/services/actions/create_env.pyi +19 -0
  41. amsdal/cloud/services/actions/create_session.cpython-311-darwin.so +0 -0
  42. amsdal/cloud/services/actions/create_session.pyi +17 -0
  43. amsdal/cloud/services/actions/delete_allowlist_ip.cpython-311-darwin.so +0 -0
  44. amsdal/cloud/services/actions/delete_allowlist_ip.pyi +19 -0
  45. amsdal/cloud/services/actions/delete_basic_auth.cpython-311-darwin.so +0 -0
  46. amsdal/cloud/services/actions/delete_basic_auth.pyi +20 -0
  47. amsdal/cloud/services/actions/delete_dependency.cpython-311-darwin.so +0 -0
  48. amsdal/cloud/services/actions/delete_dependency.pyi +21 -0
  49. amsdal/cloud/services/actions/delete_env.cpython-311-darwin.so +0 -0
  50. amsdal/cloud/services/actions/delete_env.pyi +21 -0
  51. amsdal/cloud/services/actions/delete_secret.cpython-311-darwin.so +0 -0
  52. amsdal/cloud/services/actions/delete_secret.pyi +21 -0
  53. amsdal/cloud/services/actions/destroy_deploy.cpython-311-darwin.so +0 -0
  54. amsdal/cloud/services/actions/destroy_deploy.pyi +18 -0
  55. amsdal/cloud/services/actions/expose_db.cpython-311-darwin.so +0 -0
  56. amsdal/cloud/services/actions/expose_db.pyi +22 -0
  57. amsdal/cloud/services/actions/get_basic_auth_credentials.cpython-311-darwin.so +0 -0
  58. amsdal/cloud/services/actions/get_basic_auth_credentials.pyi +21 -0
  59. amsdal/cloud/services/actions/get_monitoring_info.cpython-311-darwin.so +0 -0
  60. amsdal/cloud/services/actions/get_monitoring_info.pyi +21 -0
  61. amsdal/cloud/services/actions/list_dependencies.cpython-311-darwin.so +0 -0
  62. amsdal/cloud/services/actions/list_dependencies.pyi +21 -0
  63. amsdal/cloud/services/actions/list_deploys.cpython-311-darwin.so +0 -0
  64. amsdal/cloud/services/actions/list_deploys.pyi +19 -0
  65. amsdal/cloud/services/actions/list_envs.cpython-311-darwin.so +0 -0
  66. amsdal/cloud/services/actions/list_envs.pyi +20 -0
  67. amsdal/cloud/services/actions/list_secrets.cpython-311-darwin.so +0 -0
  68. amsdal/cloud/services/actions/list_secrets.pyi +22 -0
  69. amsdal/cloud/services/actions/manager.cpython-311-darwin.so +0 -0
  70. amsdal/cloud/services/actions/manager.pyi +278 -0
  71. amsdal/cloud/services/actions/signup_action.cpython-311-darwin.so +0 -0
  72. amsdal/cloud/services/actions/signup_action.pyi +20 -0
  73. amsdal/cloud/services/actions/update_deploy.cpython-311-darwin.so +0 -0
  74. amsdal/cloud/services/actions/update_deploy.pyi +19 -0
  75. amsdal/cloud/services/auth/__init__.cpython-311-darwin.so +0 -0
  76. amsdal/cloud/services/auth/__init__.pyi +0 -0
  77. amsdal/cloud/services/auth/base.cpython-311-darwin.so +0 -0
  78. amsdal/cloud/services/auth/base.pyi +6 -0
  79. amsdal/cloud/services/auth/credentials.cpython-311-darwin.so +0 -0
  80. amsdal/cloud/services/auth/credentials.pyi +30 -0
  81. amsdal/cloud/services/auth/manager.cpython-311-darwin.so +0 -0
  82. amsdal/cloud/services/auth/manager.pyi +26 -0
  83. amsdal/cloud/services/auth/signup_service.cpython-311-darwin.so +0 -0
  84. amsdal/cloud/services/auth/signup_service.pyi +32 -0
  85. amsdal/cloud/services/auth/token.cpython-311-darwin.so +0 -0
  86. amsdal/cloud/services/auth/token.pyi +27 -0
  87. amsdal/configs/__init__.py +0 -0
  88. amsdal/configs/__init__.pyi +0 -0
  89. amsdal/configs/constants.py +33 -0
  90. amsdal/configs/constants.pyi +22 -0
  91. amsdal/configs/main.py +274 -0
  92. amsdal/configs/main.pyi +178 -0
  93. amsdal/context/__init__.py +0 -0
  94. amsdal/context/__init__.pyi +0 -0
  95. amsdal/context/manager.py +69 -0
  96. amsdal/context/manager.pyi +50 -0
  97. amsdal/contrib/__init__.cpython-311-darwin.so +0 -0
  98. amsdal/contrib/__init__.pyi +0 -0
  99. amsdal/contrib/app_config.py +7 -0
  100. amsdal/contrib/app_config.pyi +6 -0
  101. amsdal/contrib/auth/__init__.py +0 -0
  102. amsdal/contrib/auth/__init__.pyi +0 -0
  103. amsdal/contrib/auth/app.py +27 -0
  104. amsdal/contrib/auth/app.pyi +15 -0
  105. amsdal/contrib/auth/decorators/__init__.py +35 -0
  106. amsdal/contrib/auth/decorators/__init__.pyi +6 -0
  107. amsdal/contrib/auth/errors.py +7 -0
  108. amsdal/contrib/auth/errors.pyi +4 -0
  109. amsdal/contrib/auth/fixtures/basic_permissions.json +64 -0
  110. amsdal/contrib/auth/lifecycle/__init__.py +0 -0
  111. amsdal/contrib/auth/lifecycle/__init__.pyi +0 -0
  112. amsdal/contrib/auth/lifecycle/consumer.py +394 -0
  113. amsdal/contrib/auth/lifecycle/consumer.pyi +108 -0
  114. amsdal/contrib/auth/migrations/0000_initial.py +87 -0
  115. amsdal/contrib/auth/models/__init__.py +0 -0
  116. amsdal/contrib/auth/models/login_session.py +118 -0
  117. amsdal/contrib/auth/models/permission.py +23 -0
  118. amsdal/contrib/auth/models/user.py +106 -0
  119. amsdal/contrib/auth/settings.py +36 -0
  120. amsdal/contrib/auth/settings.pyi +26 -0
  121. amsdal/contrib/frontend_configs/__init__.py +0 -0
  122. amsdal/contrib/frontend_configs/__init__.pyi +0 -0
  123. amsdal/contrib/frontend_configs/app.py +24 -0
  124. amsdal/contrib/frontend_configs/app.pyi +19 -0
  125. amsdal/contrib/frontend_configs/constants.py +1 -0
  126. amsdal/contrib/frontend_configs/constants.pyi +1 -0
  127. amsdal/contrib/frontend_configs/conversion/__init__.py +5 -0
  128. amsdal/contrib/frontend_configs/conversion/__init__.pyi +3 -0
  129. amsdal/contrib/frontend_configs/conversion/convert.py +310 -0
  130. amsdal/contrib/frontend_configs/conversion/convert.pyi +22 -0
  131. amsdal/contrib/frontend_configs/lifecycle/__init__.py +0 -0
  132. amsdal/contrib/frontend_configs/lifecycle/__init__.pyi +0 -0
  133. amsdal/contrib/frontend_configs/lifecycle/consumer.py +306 -0
  134. amsdal/contrib/frontend_configs/lifecycle/consumer.pyi +98 -0
  135. amsdal/contrib/frontend_configs/migrations/0000_initial.py +227 -0
  136. amsdal/contrib/frontend_configs/migrations/0001_update_frontend_control_config.py +245 -0
  137. amsdal/contrib/frontend_configs/migrations/0002_add_button_and_invoke_actions.py +352 -0
  138. amsdal/contrib/frontend_configs/models/__init__.py +0 -0
  139. amsdal/contrib/frontend_configs/models/frontend_activator_config.py +22 -0
  140. amsdal/contrib/frontend_configs/models/frontend_config_async_validator.py +11 -0
  141. amsdal/contrib/frontend_configs/models/frontend_config_control_action.py +110 -0
  142. amsdal/contrib/frontend_configs/models/frontend_config_group_validator.py +21 -0
  143. amsdal/contrib/frontend_configs/models/frontend_config_option.py +12 -0
  144. amsdal/contrib/frontend_configs/models/frontend_config_skip_none_base.py +17 -0
  145. amsdal/contrib/frontend_configs/models/frontend_config_slider_option.py +13 -0
  146. amsdal/contrib/frontend_configs/models/frontend_config_text_mask.py +14 -0
  147. amsdal/contrib/frontend_configs/models/frontend_config_validator.py +28 -0
  148. amsdal/contrib/frontend_configs/models/frontend_control_config.py +108 -0
  149. amsdal/contrib/frontend_configs/models/frontend_model_config.py +14 -0
  150. amsdal/contrib/frontend_configs/utils.py +29 -0
  151. amsdal/contrib/frontend_configs/utils.pyi +17 -0
  152. amsdal/errors.py +31 -0
  153. amsdal/errors.pyi +12 -0
  154. amsdal/fixtures/__init__.cpython-311-darwin.so +0 -0
  155. amsdal/fixtures/__init__.pyi +0 -0
  156. amsdal/fixtures/manager.cpython-311-darwin.so +0 -0
  157. amsdal/fixtures/manager.pyi +170 -0
  158. amsdal/fixtures/utils.cpython-311-darwin.so +0 -0
  159. amsdal/fixtures/utils.pyi +9 -0
  160. amsdal/manager.cpython-311-darwin.so +0 -0
  161. amsdal/manager.pyi +265 -0
  162. amsdal/mixins/__init__.cpython-311-darwin.so +0 -0
  163. amsdal/mixins/__init__.pyi +0 -0
  164. amsdal/mixins/class_versions_mixin.cpython-311-darwin.so +0 -0
  165. amsdal/mixins/class_versions_mixin.pyi +12 -0
  166. amsdal/models/__init__.py +19 -0
  167. amsdal/models/core/__init__.py +0 -0
  168. amsdal/models/core/class_object.py +38 -0
  169. amsdal/models/core/class_property.py +26 -0
  170. amsdal/models/core/file.py +243 -0
  171. amsdal/models/core/fixture.py +25 -0
  172. amsdal/models/core/option.py +11 -0
  173. amsdal/models/core/storage_metadata.py +15 -0
  174. amsdal/models/core/validator.py +12 -0
  175. amsdal/models/mixins.py +31 -0
  176. amsdal/models/types/__init__.py +0 -0
  177. amsdal/models/types/object.py +26 -0
  178. amsdal/py.typed +0 -0
  179. amsdal/queryset/__init__.py +21 -0
  180. amsdal/queryset/__init__.pyi +6 -0
  181. amsdal/schemas/__init__.py +0 -0
  182. amsdal/schemas/__init__.pyi +0 -0
  183. amsdal/schemas/core/class_object/model.json +51 -0
  184. amsdal/schemas/core/class_object/properties/display_name.py +9 -0
  185. amsdal/schemas/core/class_property/model.json +41 -0
  186. amsdal/schemas/core/file/hooks/pre_create.py +24 -0
  187. amsdal/schemas/core/file/hooks/pre_update.py +24 -0
  188. amsdal/schemas/core/file/model.json +23 -0
  189. amsdal/schemas/core/file/properties/from_file.py +34 -0
  190. amsdal/schemas/core/file/properties/mimetype.py +13 -0
  191. amsdal/schemas/core/file/properties/str.py +6 -0
  192. amsdal/schemas/core/file/properties/to_file.py +24 -0
  193. amsdal/schemas/core/file/properties/validate_data.py +31 -0
  194. amsdal/schemas/core/fixture/model.json +35 -0
  195. amsdal/schemas/core/option/model.json +19 -0
  196. amsdal/schemas/core/storage_metadata/model.json +52 -0
  197. amsdal/schemas/core/validator/model.json +19 -0
  198. amsdal/schemas/interfaces.py +25 -0
  199. amsdal/schemas/interfaces.pyi +20 -0
  200. amsdal/schemas/manager.cpython-311-darwin.so +0 -0
  201. amsdal/schemas/manager.py +0 -0
  202. amsdal/schemas/manager.pyi +0 -0
  203. amsdal/schemas/mixins/__init__.py +0 -0
  204. amsdal/schemas/mixins/__init__.pyi +0 -0
  205. amsdal/schemas/mixins/check_dependencies_mixin.py +130 -0
  206. amsdal/schemas/mixins/check_dependencies_mixin.pyi +45 -0
  207. amsdal/schemas/mixins/verify_schemas_mixin.py +96 -0
  208. amsdal/schemas/mixins/verify_schemas_mixin.pyi +33 -0
  209. amsdal/schemas/repository.py +84 -0
  210. amsdal/schemas/repository.pyi +22 -0
  211. amsdal/schemas/types/anything/model.json +7 -0
  212. amsdal/schemas/types/array/model.json +7 -0
  213. amsdal/schemas/types/binary/model.json +7 -0
  214. amsdal/schemas/types/boolean/model.json +17 -0
  215. amsdal/schemas/types/date/model.json +7 -0
  216. amsdal/schemas/types/datetime/model.json +7 -0
  217. amsdal/schemas/types/dictionary/model.json +8 -0
  218. amsdal/schemas/types/number/model.json +8 -0
  219. amsdal/schemas/types/object/model.json +53 -0
  220. amsdal/schemas/types/string/model.json +8 -0
  221. amsdal/schemas/utils.py +16 -0
  222. amsdal/schemas/utils.pyi +10 -0
  223. amsdal/services/__init__.py +11 -0
  224. amsdal/services/__init__.pyi +4 -0
  225. amsdal/services/external_connections.py +262 -0
  226. amsdal/services/external_connections.pyi +190 -0
  227. amsdal/services/external_model_generator.py +350 -0
  228. amsdal/services/external_model_generator.pyi +134 -0
  229. amsdal/services/transaction_execution.cpython-311-darwin.so +0 -0
  230. amsdal/services/transaction_execution.pyi +93 -0
  231. amsdal/storages/__init__.py +20 -0
  232. amsdal/storages/__init__.pyi +8 -0
  233. amsdal/storages/file_system.py +214 -0
  234. amsdal/storages/file_system.pyi +36 -0
  235. amsdal/transactions/__init__.py +13 -0
  236. amsdal/transactions/__init__.pyi +4 -0
  237. amsdal/utils/__init__.py +0 -0
  238. amsdal/utils/__init__.pyi +0 -0
  239. amsdal/utils/contrib_paths.py +23 -0
  240. amsdal/utils/contrib_paths.pyi +14 -0
  241. amsdal/utils/rollback/__init__.py +440 -0
  242. amsdal/utils/rollback/__init__.pyi +38 -0
  243. amsdal/utils/tests/__init__.py +0 -0
  244. amsdal/utils/tests/enums.py +16 -0
  245. amsdal/utils/tests/factories.py +49 -0
  246. amsdal/utils/tests/helpers.py +331 -0
  247. amsdal/utils/tests/migrations.py +157 -0
  248. amsdal-0.5.23.dist-info/METADATA +373 -0
  249. amsdal-0.5.23.dist-info/RECORD +252 -0
  250. amsdal-0.5.23.dist-info/WHEEL +5 -0
  251. amsdal-0.5.23.dist-info/licenses/LICENSE.txt +107 -0
  252. amsdal-0.5.23.dist-info/top_level.txt +1 -0
@@ -0,0 +1,440 @@
1
+ import amsdal_glue as glue
2
+ from amsdal_data.application import AsyncDataApplication
3
+ from amsdal_data.application import DataApplication
4
+ from amsdal_data.transactions.decorators import async_transaction
5
+ from amsdal_data.transactions.decorators import transaction
6
+ from amsdal_data.transactions.errors import AmsdalTransactionError
7
+ from amsdal_models.classes.class_manager import ClassManager
8
+ from amsdal_models.querysets.executor import LAKEHOUSE_DB_ALIAS
9
+
10
+
11
+ @transaction
12
+ def rollback_to_timestamp(timestamp: float) -> None:
13
+ """
14
+ Rollback the data to the given timestamp
15
+ Args:
16
+ timestamp (float): The timestamp to rollback the data to.
17
+ Returns:
18
+ None
19
+ """
20
+ class_manager = ClassManager()
21
+
22
+ lakehouse_connection = (
23
+ DataApplication()._application.lakehouse_connection_manager.get_connection_pool('Company').get_connection()
24
+ )
25
+
26
+ metadatas_to_delete = lakehouse_connection.query(
27
+ query=glue.QueryStatement(
28
+ table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
29
+ where=glue.Conditions(
30
+ glue.Condition(
31
+ left=glue.FieldReferenceExpression(
32
+ field_reference=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
33
+ ),
34
+ lookup=glue.FieldLookup.GT,
35
+ right=glue.Value(timestamp),
36
+ ),
37
+ glue.Condition(
38
+ left=glue.FieldReferenceExpression(
39
+ field_reference=glue.FieldReference(
40
+ field=glue.Field(name='prior_version'),
41
+ table_name='Metadata',
42
+ ),
43
+ ),
44
+ lookup=glue.FieldLookup.ISNULL,
45
+ right=glue.Value(True),
46
+ ),
47
+ ),
48
+ )
49
+ )
50
+
51
+ ids_to_ignore = [m.data['object_id'] for m in metadatas_to_delete]
52
+
53
+ metadatas_to_revert = lakehouse_connection.query(
54
+ query=glue.QueryStatement(
55
+ table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
56
+ where=glue.Conditions(
57
+ glue.Condition(
58
+ left=glue.FieldReferenceExpression(
59
+ field_reference=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
60
+ ),
61
+ lookup=glue.FieldLookup.GT,
62
+ right=glue.Value(timestamp),
63
+ ),
64
+ glue.Condition(
65
+ left=glue.FieldReferenceExpression(
66
+ field_reference=glue.FieldReference(
67
+ field=glue.Field(name='prior_version'),
68
+ table_name='Metadata',
69
+ ),
70
+ ),
71
+ lookup=glue.FieldLookup.ISNULL,
72
+ right=glue.Value(False),
73
+ ),
74
+ ),
75
+ )
76
+ )
77
+
78
+ transaction_ids = {m.data['transaction']['ref']['object_id'] for m in metadatas_to_revert}
79
+ transaction_ids.update({m.data['transaction']['ref']['object_id'] for m in metadatas_to_delete})
80
+ ids_to_revert = [
81
+ (m.data['object_id'], m.data['class_schema_reference']['ref']['object_id'])
82
+ for m in metadatas_to_revert
83
+ if m.data['object_id'] not in ids_to_ignore
84
+ ]
85
+
86
+ if transaction_ids:
87
+ _conditions = []
88
+ for transaction_id in transaction_ids:
89
+ _parent_field = glue.Field(
90
+ name='transaction',
91
+ child=glue.Field(
92
+ name='ref',
93
+ child=glue.Field(name='object_id'),
94
+ ),
95
+ )
96
+ _parent_field.child.parent = _parent_field # type: ignore[union-attr]
97
+ _parent_field.child.child.parent = _parent_field.child # type: ignore[union-attr]
98
+ _conditions.append(
99
+ glue.Condition(
100
+ left=glue.FieldReferenceExpression(
101
+ field_reference=glue.FieldReference(field=_parent_field, table_name='Metadata'),
102
+ output_type=str,
103
+ ),
104
+ lookup=glue.FieldLookup.EQ,
105
+ right=glue.Value(transaction_id, output_type=str),
106
+ )
107
+ )
108
+
109
+ conflict_metadata = lakehouse_connection.query(
110
+ query=glue.QueryStatement(
111
+ table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
112
+ where=glue.Conditions(
113
+ glue.Condition(
114
+ left=glue.FieldReferenceExpression(
115
+ field_reference=glue.FieldReference(
116
+ field=glue.Field(name='updated_at'),
117
+ table_name='Metadata',
118
+ ),
119
+ ),
120
+ lookup=glue.FieldLookup.LTE,
121
+ right=glue.Value(timestamp),
122
+ ),
123
+ glue.Conditions(*_conditions, connector=glue.FilterConnector.OR),
124
+ ),
125
+ )
126
+ )
127
+ if conflict_metadata:
128
+ msg = 'Cannot rollback to this timestamp because it will conflict with other transactions'
129
+ raise AmsdalTransactionError(msg)
130
+
131
+ for m in metadatas_to_delete:
132
+ class_name = m.data['class_schema_reference']['ref']['object_id']
133
+ model_class = class_manager.import_class(class_name)
134
+ obj = (
135
+ model_class.objects.filter(_address__object_id=m.data['object_id'])
136
+ .using(LAKEHOUSE_DB_ALIAS)
137
+ .latest()
138
+ .first()
139
+ .execute()
140
+ )
141
+
142
+ if obj and not obj.get_metadata().is_deleted:
143
+ obj.delete()
144
+
145
+ for object_id, class_name in ids_to_revert:
146
+ model_class = class_manager.import_class(class_name)
147
+
148
+ obj = (
149
+ model_class.objects.filter(_address__object_id=object_id)
150
+ .using(LAKEHOUSE_DB_ALIAS)
151
+ .latest()
152
+ .first()
153
+ .execute()
154
+ )
155
+ old_obj = obj.previous_version() # type: ignore[union-attr]
156
+ # old_obj = (
157
+ # model_class.objects.filter(_address__object_id=object_id, _metadata__updated_at__lte=timestamp)
158
+ # .using(LAKEHOUSE_DB_ALIAS)
159
+ # .order_by('-_metadata__updated_at')
160
+ # .first()
161
+ # .execute()
162
+ # )
163
+
164
+ if obj and old_obj:
165
+ for field, value in old_obj.model_dump().items():
166
+ setattr(obj, field, value)
167
+
168
+ obj.save()
169
+
170
+ if old_obj.get_metadata().is_deleted:
171
+ obj.delete()
172
+
173
+
174
+ @transaction
175
+ def rollback_transaction(transaction_id: str) -> None:
176
+ """
177
+ Rollback the data to the point in time before the given transaction
178
+ Args:
179
+ transaction_id (str): The transaction ID to rollback the data to.
180
+ Returns:
181
+ None
182
+ """
183
+
184
+ lakehouse_connection = (
185
+ DataApplication()._application.lakehouse_connection_manager.get_connection_pool('Company').get_connection()
186
+ )
187
+
188
+ _parent_field = glue.Field(
189
+ name='transaction',
190
+ child=glue.Field(
191
+ name='ref',
192
+ child=glue.Field(name='object_id'),
193
+ ),
194
+ )
195
+ _parent_field.child.parent = _parent_field # type: ignore[union-attr]
196
+ _parent_field.child.child.parent = _parent_field.child # type: ignore[union-attr]
197
+
198
+ metadatas_to_revert = lakehouse_connection.query(
199
+ query=glue.QueryStatement(
200
+ table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
201
+ where=glue.Conditions(
202
+ glue.Condition(
203
+ left=glue.FieldReferenceExpression(
204
+ field_reference=glue.FieldReference(field=_parent_field, table_name='Metadata'),
205
+ output_type=str,
206
+ ),
207
+ lookup=glue.FieldLookup.EQ,
208
+ right=glue.Value(transaction_id, output_type=str),
209
+ )
210
+ ),
211
+ order_by=[
212
+ glue.OrderByQuery(
213
+ field=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
214
+ direction=glue.OrderDirection.DESC,
215
+ )
216
+ ],
217
+ )
218
+ )
219
+
220
+ if not metadatas_to_revert:
221
+ msg = 'Transaction not found'
222
+ raise AmsdalTransactionError(msg)
223
+
224
+ updated_at = metadatas_to_revert[0].data['updated_at']
225
+ rollback_to_timestamp(updated_at)
226
+
227
+
228
+ @async_transaction
229
+ async def async_rollback_to_timestamp(timestamp: float) -> None:
230
+ """
231
+ Rollback the data to the given timestamp
232
+ Args:
233
+ timestamp (float): The timestamp to rollback the data to.
234
+ Returns:
235
+ None
236
+ """
237
+ class_manager = ClassManager()
238
+
239
+ lakehouse_connection = await (
240
+ AsyncDataApplication()._application.lakehouse_connection_manager.get_connection_pool('Company').get_connection()
241
+ )
242
+
243
+ metadatas_to_delete = await lakehouse_connection.query(
244
+ query=glue.QueryStatement(
245
+ table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
246
+ where=glue.Conditions(
247
+ glue.Condition(
248
+ left=glue.FieldReferenceExpression(
249
+ field_reference=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
250
+ ),
251
+ lookup=glue.FieldLookup.GT,
252
+ right=glue.Value(timestamp),
253
+ ),
254
+ glue.Condition(
255
+ left=glue.FieldReferenceExpression(
256
+ field_reference=glue.FieldReference(
257
+ field=glue.Field(name='prior_version'),
258
+ table_name='Metadata',
259
+ ),
260
+ ),
261
+ lookup=glue.FieldLookup.ISNULL,
262
+ right=glue.Value(True),
263
+ ),
264
+ ),
265
+ )
266
+ )
267
+
268
+ ids_to_ignore = [m.data['object_id'] for m in metadatas_to_delete]
269
+
270
+ metadatas_to_revert = await lakehouse_connection.query(
271
+ query=glue.QueryStatement(
272
+ table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
273
+ where=glue.Conditions(
274
+ glue.Condition(
275
+ left=glue.FieldReferenceExpression(
276
+ field_reference=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
277
+ ),
278
+ lookup=glue.FieldLookup.GT,
279
+ right=glue.Value(timestamp),
280
+ ),
281
+ glue.Condition(
282
+ left=glue.FieldReferenceExpression(
283
+ field_reference=glue.FieldReference(
284
+ field=glue.Field(name='prior_version'), table_name='Metadata'
285
+ ),
286
+ ),
287
+ lookup=glue.FieldLookup.ISNULL,
288
+ right=glue.Value(False),
289
+ ),
290
+ ),
291
+ )
292
+ )
293
+
294
+ transaction_ids = {m.data['transaction']['ref']['object_id'] for m in metadatas_to_revert}
295
+ transaction_ids.update({m.data['transaction']['ref']['object_id'] for m in metadatas_to_delete})
296
+ ids_to_revert = [
297
+ (m.data['object_id'], m.data['class_schema_reference']['ref']['object_id'])
298
+ for m in metadatas_to_revert
299
+ if m.data['object_id'] not in ids_to_ignore
300
+ ]
301
+
302
+ if transaction_ids:
303
+ _conditions = []
304
+ for transaction_id in transaction_ids:
305
+ _parent_field = glue.Field(
306
+ name='transaction',
307
+ child=glue.Field(
308
+ name='ref',
309
+ child=glue.Field(name='object_id'),
310
+ ),
311
+ )
312
+ _parent_field.child.parent = _parent_field # type: ignore[union-attr]
313
+ _parent_field.child.child.parent = _parent_field.child # type: ignore[union-attr]
314
+ _conditions.append(
315
+ glue.Condition(
316
+ left=glue.FieldReferenceExpression(
317
+ field_reference=glue.FieldReference(field=_parent_field, table_name='Metadata'),
318
+ output_type=str,
319
+ ),
320
+ lookup=glue.FieldLookup.EQ,
321
+ right=glue.Value(transaction_id, output_type=str),
322
+ )
323
+ )
324
+
325
+ conflict_metadata = await lakehouse_connection.query(
326
+ query=glue.QueryStatement(
327
+ table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
328
+ where=glue.Conditions(
329
+ glue.Condition(
330
+ left=glue.FieldReferenceExpression(
331
+ field_reference=glue.FieldReference(
332
+ field=glue.Field(name='updated_at'),
333
+ table_name='Metadata',
334
+ ),
335
+ ),
336
+ lookup=glue.FieldLookup.LTE,
337
+ right=glue.Value(timestamp),
338
+ ),
339
+ glue.Conditions(*_conditions, connector=glue.FilterConnector.OR),
340
+ ),
341
+ )
342
+ )
343
+ if conflict_metadata:
344
+ msg = 'Cannot rollback to this timestamp because it will conflict with other transactions'
345
+ raise AmsdalTransactionError(msg)
346
+
347
+ for m in metadatas_to_delete:
348
+ class_name = m.data['class_schema_reference']['ref']['object_id']
349
+ model_class = class_manager.import_class(class_name)
350
+ obj = await (
351
+ model_class.objects.filter(_address__object_id=m.data['object_id'])
352
+ .using(LAKEHOUSE_DB_ALIAS)
353
+ .latest()
354
+ .first()
355
+ .aexecute()
356
+ )
357
+
358
+ if obj and not (await obj.aget_metadata()).is_deleted:
359
+ await obj.adelete()
360
+
361
+ for object_id, class_name in ids_to_revert:
362
+ model_class = class_manager.import_class(class_name)
363
+
364
+ obj = await (
365
+ model_class.objects.filter(_address__object_id=object_id)
366
+ .using(LAKEHOUSE_DB_ALIAS)
367
+ .latest()
368
+ .first()
369
+ .aexecute()
370
+ )
371
+ old_obj = await obj.aprevious_version() # type: ignore[union-attr]
372
+ # old_obj = await (
373
+ # model_class.objects.filter(_address__object_id=object_id, _metadata__updated_at__lte=timestamp)
374
+ # .using(LAKEHOUSE_DB_ALIAS)
375
+ # .order_by('-_metadata__updated_at')
376
+ # .first()
377
+ # .aexecute()
378
+ # )
379
+
380
+ if obj and old_obj:
381
+ for field, value in (await old_obj.amodel_dump()).items():
382
+ setattr(obj, field, value)
383
+
384
+ await obj.asave()
385
+
386
+ if (await old_obj.aget_metadata()).is_deleted:
387
+ await obj.adelete()
388
+
389
+
390
+ @async_transaction
391
+ async def async_rollback_transaction(transaction_id: str) -> None:
392
+ """
393
+ Rollback the data to the point in time before the given transaction
394
+ Args:
395
+ transaction_id (str): The transaction ID to rollback the data to.
396
+ Returns:
397
+ None
398
+ """
399
+ lakehouse_connection = await (
400
+ AsyncDataApplication()._application.lakehouse_connection_manager.get_connection_pool('Company').get_connection()
401
+ )
402
+
403
+ _parent_field = glue.Field(
404
+ name='transaction',
405
+ child=glue.Field(
406
+ name='ref',
407
+ child=glue.Field(name='object_id'),
408
+ ),
409
+ )
410
+ _parent_field.child.parent = _parent_field # type: ignore[union-attr]
411
+ _parent_field.child.child.parent = _parent_field.child # type: ignore[union-attr]
412
+
413
+ metadatas_to_revert = await lakehouse_connection.query(
414
+ query=glue.QueryStatement(
415
+ table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
416
+ where=glue.Conditions(
417
+ glue.Condition(
418
+ left=glue.FieldReferenceExpression(
419
+ field_reference=glue.FieldReference(field=_parent_field, table_name='Metadata'),
420
+ output_type=str,
421
+ ),
422
+ lookup=glue.FieldLookup.EQ,
423
+ right=glue.Value(transaction_id, output_type=str),
424
+ )
425
+ ),
426
+ order_by=[
427
+ glue.OrderByQuery(
428
+ field=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
429
+ direction=glue.OrderDirection.DESC,
430
+ )
431
+ ],
432
+ )
433
+ )
434
+
435
+ if not metadatas_to_revert:
436
+ msg = 'Transaction not found'
437
+ raise AmsdalTransactionError(msg)
438
+
439
+ updated_at = metadatas_to_revert[0].data['updated_at']
440
+ await async_rollback_to_timestamp(updated_at) # type: ignore[misc]
@@ -0,0 +1,38 @@
1
+ from amsdal_data.transactions.decorators import async_transaction, transaction
2
+
3
+ @transaction
4
+ def rollback_to_timestamp(timestamp: float) -> None:
5
+ """
6
+ Rollback the data to the given timestamp
7
+ Args:
8
+ timestamp (float): The timestamp to rollback the data to.
9
+ Returns:
10
+ None
11
+ """
12
+ @transaction
13
+ def rollback_transaction(transaction_id: str) -> None:
14
+ """
15
+ Rollback the data to the point in time before the given transaction
16
+ Args:
17
+ transaction_id (str): The transaction ID to rollback the data to.
18
+ Returns:
19
+ None
20
+ """
21
+ @async_transaction
22
+ async def async_rollback_to_timestamp(timestamp: float) -> None:
23
+ """
24
+ Rollback the data to the given timestamp
25
+ Args:
26
+ timestamp (float): The timestamp to rollback the data to.
27
+ Returns:
28
+ None
29
+ """
30
+ @async_transaction
31
+ async def async_rollback_transaction(transaction_id: str) -> None:
32
+ """
33
+ Rollback the data to the point in time before the given transaction
34
+ Args:
35
+ transaction_id (str): The transaction ID to rollback the data to.
36
+ Returns:
37
+ None
38
+ """
File without changes
@@ -0,0 +1,16 @@
1
+ from enum import Enum
2
+
3
+
4
+ class DbExecutionType(str, Enum):
5
+ lakehouse_only = 'lakehouse_only'
6
+ include_state_db = 'include_state_db'
7
+
8
+
9
+ class StateOption(str, Enum):
10
+ sqlite = 'sqlite'
11
+ postgres = 'postgres'
12
+
13
+
14
+ class LakehouseOption(str, Enum):
15
+ postgres = 'postgres'
16
+ sqlite = 'sqlite'
@@ -0,0 +1,49 @@
1
+ import contextlib
2
+ from typing import Any
3
+ from typing import Generic
4
+ from typing import TypeVar
5
+ from typing import Union
6
+ from typing import get_origin
7
+
8
+ from amsdal_models.classes.model import LegacyModel
9
+ from amsdal_models.classes.model import Model
10
+ from amsdal_utils.models.data_models.reference import Reference
11
+ from polyfactory.factories.base import BuildContext
12
+ from polyfactory.field_meta import FieldMeta
13
+ from polyfactory.field_meta import Null
14
+
15
+ try:
16
+ import polyfactory.factories.pydantic_factory as factories
17
+ except ImportError:
18
+ _msg = '"polyfactory" package is required for using this module. Use "pip install amsdal[factory]" to install it.'
19
+ raise ImportError(_msg) from None
20
+
21
+
22
+ T = TypeVar('T', bound=Model)
23
+
24
+
25
+ class AmsdalFactory(Generic[T], factories.ModelFactory[T]):
26
+ __is_base_factory__ = True
27
+
28
+ @classmethod
29
+ def get_field_value(
30
+ cls,
31
+ field_meta: FieldMeta,
32
+ field_build_parameters: Any | None = None,
33
+ build_context: BuildContext | None = None,
34
+ ) -> Any:
35
+ if get_origin(field_meta.annotation) is Union and field_meta.default is Null:
36
+ with contextlib.suppress(TypeError):
37
+ is_class_definition = any(
38
+ issubclass(arg, LegacyModel) for arg in field_meta.annotation.__args__
39
+ ) and any(issubclass(arg, Reference) for arg in field_meta.annotation.__args__)
40
+ is_optional = any(issubclass(arg, type(None)) for arg in field_meta.annotation.__args__)
41
+
42
+ if is_optional:
43
+ field_meta.annotation = type(None)
44
+ elif is_class_definition:
45
+ for _type in field_meta.annotation.__args__:
46
+ if not issubclass(_type, LegacyModel | type(None) | Reference):
47
+ field_meta.annotation = _type
48
+
49
+ return super().get_field_value(field_meta, field_build_parameters, build_context)