amsdal 0.3.5__cp311-cp311-macosx_10_9_universal2.whl → 0.4.0__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 (210) hide show
  1. amsdal/__about__.py +1 -1
  2. amsdal/__migrations__/0000_initial.py +34 -25
  3. amsdal/__migrations__/0001_datetime_type.py +4 -4
  4. amsdal/__migrations__/0002_fixture_order.py +7 -3
  5. amsdal/__migrations__/0003_schema_type_in_class_meta.py +3 -15
  6. amsdal/cloud/__init__.cpython-311-darwin.so +0 -0
  7. amsdal/cloud/client.cpython-311-darwin.so +0 -0
  8. amsdal/cloud/constants.cpython-311-darwin.so +0 -0
  9. amsdal/cloud/enums.cpython-311-darwin.so +0 -0
  10. amsdal/cloud/models/__init__.cpython-311-darwin.so +0 -0
  11. amsdal/cloud/models/base.cpython-311-darwin.so +0 -0
  12. amsdal/cloud/services/__init__.cpython-311-darwin.so +0 -0
  13. amsdal/cloud/services/actions/__init__.cpython-311-darwin.so +0 -0
  14. amsdal/cloud/services/actions/add_allowlist_ip.cpython-311-darwin.so +0 -0
  15. amsdal/cloud/services/actions/add_basic_auth.cpython-311-darwin.so +0 -0
  16. amsdal/cloud/services/actions/add_dependency.cpython-311-darwin.so +0 -0
  17. amsdal/cloud/services/actions/add_secret.cpython-311-darwin.so +0 -0
  18. amsdal/cloud/services/actions/base.cpython-311-darwin.so +0 -0
  19. amsdal/cloud/services/actions/create_deploy.cpython-311-darwin.so +0 -0
  20. amsdal/cloud/services/actions/create_env.cpython-311-darwin.so +0 -0
  21. amsdal/cloud/services/actions/create_session.cpython-311-darwin.so +0 -0
  22. amsdal/cloud/services/actions/delete_allowlist_ip.cpython-311-darwin.so +0 -0
  23. amsdal/cloud/services/actions/delete_basic_auth.cpython-311-darwin.so +0 -0
  24. amsdal/cloud/services/actions/delete_dependency.cpython-311-darwin.so +0 -0
  25. amsdal/cloud/services/actions/delete_env.cpython-311-darwin.so +0 -0
  26. amsdal/cloud/services/actions/delete_secret.cpython-311-darwin.so +0 -0
  27. amsdal/cloud/services/actions/destroy_deploy.cpython-311-darwin.so +0 -0
  28. amsdal/cloud/services/actions/expose_db.cpython-311-darwin.so +0 -0
  29. amsdal/cloud/services/actions/get_basic_auth_credentials.cpython-311-darwin.so +0 -0
  30. amsdal/cloud/services/actions/get_monitoring_info.cpython-311-darwin.so +0 -0
  31. amsdal/cloud/services/actions/list_dependencies.cpython-311-darwin.so +0 -0
  32. amsdal/cloud/services/actions/list_deploys.cpython-311-darwin.so +0 -0
  33. amsdal/cloud/services/actions/list_envs.cpython-311-darwin.so +0 -0
  34. amsdal/cloud/services/actions/list_secrets.cpython-311-darwin.so +0 -0
  35. amsdal/cloud/services/actions/manager.cpython-311-darwin.so +0 -0
  36. amsdal/cloud/services/actions/signup_action.cpython-311-darwin.so +0 -0
  37. amsdal/cloud/services/actions/update_deploy.cpython-311-darwin.so +0 -0
  38. amsdal/cloud/services/auth/__init__.cpython-311-darwin.so +0 -0
  39. amsdal/cloud/services/auth/base.cpython-311-darwin.so +0 -0
  40. amsdal/cloud/services/auth/credentials.cpython-311-darwin.so +0 -0
  41. amsdal/cloud/services/auth/credentials.pyi +0 -1
  42. amsdal/cloud/services/auth/manager.cpython-311-darwin.so +0 -0
  43. amsdal/cloud/services/auth/signup_service.cpython-311-darwin.so +0 -0
  44. amsdal/cloud/services/auth/token.cpython-311-darwin.so +0 -0
  45. amsdal/cloud/services/auth/token.pyi +0 -1
  46. amsdal/configs/main.py +23 -19
  47. amsdal/configs/main.pyi +12 -15
  48. amsdal/contrib/__init__.cpython-311-darwin.so +0 -0
  49. amsdal/contrib/auth/lifecycle/consumer.py +10 -10
  50. amsdal/contrib/auth/migrations/0000_initial.py +41 -7
  51. amsdal/contrib/auth/models/login_session.py +66 -0
  52. amsdal/contrib/auth/models/login_session.pyi +33 -0
  53. amsdal/contrib/auth/models/permission.py +23 -0
  54. amsdal/contrib/auth/models/permission.pyi +18 -0
  55. amsdal/contrib/auth/models/user.py +106 -0
  56. amsdal/contrib/auth/models/user.pyi +46 -0
  57. amsdal/contrib/frontend_configs/conversion/convert.py +47 -15
  58. amsdal/contrib/frontend_configs/conversion/convert.pyi +0 -1
  59. amsdal/contrib/frontend_configs/lifecycle/consumer.py +32 -13
  60. amsdal/contrib/frontend_configs/lifecycle/consumer.pyi +1 -1
  61. amsdal/contrib/frontend_configs/migrations/0000_initial.py +15 -14
  62. amsdal/contrib/frontend_configs/models/__init__.py +0 -0
  63. amsdal/contrib/frontend_configs/models/__init__.pyi +0 -0
  64. amsdal/contrib/frontend_configs/models/frontend_activator_config.py +22 -0
  65. amsdal/contrib/frontend_configs/models/frontend_activator_config.pyi +12 -0
  66. amsdal/contrib/frontend_configs/models/frontend_config_async_validator.py +11 -0
  67. amsdal/contrib/frontend_configs/models/frontend_config_async_validator.pyi +7 -0
  68. amsdal/contrib/frontend_configs/models/frontend_config_control_action.py +54 -0
  69. amsdal/contrib/frontend_configs/models/frontend_config_control_action.pyi +32 -0
  70. amsdal/contrib/frontend_configs/models/frontend_config_group_validator.py +21 -0
  71. amsdal/contrib/frontend_configs/models/frontend_config_group_validator.pyi +11 -0
  72. amsdal/contrib/frontend_configs/models/frontend_config_option.py +12 -0
  73. amsdal/contrib/frontend_configs/models/frontend_config_option.pyi +8 -0
  74. amsdal/contrib/frontend_configs/models/frontend_config_skip_none_base.py +17 -0
  75. amsdal/contrib/frontend_configs/models/frontend_config_skip_none_base.pyi +8 -0
  76. amsdal/contrib/frontend_configs/models/frontend_config_slider_option.py +13 -0
  77. amsdal/contrib/frontend_configs/models/frontend_config_slider_option.pyi +9 -0
  78. amsdal/contrib/frontend_configs/models/frontend_config_text_mask.py +14 -0
  79. amsdal/contrib/frontend_configs/models/frontend_config_text_mask.pyi +10 -0
  80. amsdal/contrib/frontend_configs/models/frontend_config_validator.py +28 -0
  81. amsdal/contrib/frontend_configs/models/frontend_config_validator.pyi +15 -0
  82. amsdal/contrib/frontend_configs/models/frontend_control_config.py +87 -0
  83. amsdal/contrib/frontend_configs/models/frontend_control_config.pyi +35 -0
  84. amsdal/contrib/frontend_configs/models/frontend_model_config.py +14 -0
  85. amsdal/contrib/frontend_configs/models/frontend_model_config.pyi +9 -0
  86. amsdal/errors.py +0 -3
  87. amsdal/errors.pyi +0 -1
  88. amsdal/fixtures/__init__.cpython-311-darwin.so +0 -0
  89. amsdal/fixtures/manager.cpython-311-darwin.so +0 -0
  90. amsdal/fixtures/manager.pyi +73 -123
  91. amsdal/fixtures/utils.cpython-311-darwin.so +0 -0
  92. amsdal/fixtures/utils.pyi +9 -0
  93. amsdal/manager.cpython-311-darwin.so +0 -0
  94. amsdal/manager.pyi +4 -96
  95. amsdal/mixins/__init__.cpython-311-darwin.so +0 -0
  96. amsdal/mixins/class_versions_mixin.cpython-311-darwin.so +0 -0
  97. amsdal/models/__init__.py +0 -0
  98. amsdal/models/__init__.pyi +0 -0
  99. amsdal/models/core/__init__.py +0 -0
  100. amsdal/models/core/__init__.pyi +0 -0
  101. amsdal/models/core/class_object.py +37 -0
  102. amsdal/models/core/class_object.pyi +24 -0
  103. amsdal/models/core/class_object_meta.py +26 -0
  104. amsdal/models/core/class_object_meta.pyi +15 -0
  105. amsdal/models/core/class_property.py +19 -0
  106. amsdal/models/core/class_property.pyi +10 -0
  107. amsdal/models/core/class_property_meta.py +15 -0
  108. amsdal/models/core/class_property_meta.pyi +10 -0
  109. amsdal/models/core/file.py +156 -0
  110. amsdal/models/core/file.pyi +104 -0
  111. amsdal/models/core/fixture.py +25 -0
  112. amsdal/models/core/fixture.pyi +14 -0
  113. amsdal/models/core/option.py +11 -0
  114. amsdal/models/core/option.pyi +8 -0
  115. amsdal/models/core/validator.py +12 -0
  116. amsdal/models/core/validator.pyi +8 -0
  117. amsdal/models/types/__init__.py +0 -0
  118. amsdal/models/types/__init__.pyi +0 -0
  119. amsdal/models/types/object.py +26 -0
  120. amsdal/models/types/object.pyi +16 -0
  121. amsdal/schemas/core/file/properties/from_file.py +1 -1
  122. amsdal/schemas/core/file/properties/validate_data.py +1 -1
  123. amsdal/schemas/interfaces.py +25 -0
  124. amsdal/schemas/interfaces.pyi +20 -0
  125. amsdal/schemas/manager.cpython-311-darwin.so +0 -0
  126. amsdal/schemas/manager.py +0 -116
  127. amsdal/schemas/manager.pyi +0 -65
  128. amsdal/schemas/mixins/__init__.py +0 -0
  129. amsdal/schemas/mixins/__init__.pyi +0 -0
  130. amsdal/schemas/mixins/check_dependencies_mixin.py +115 -0
  131. amsdal/schemas/mixins/check_dependencies_mixin.pyi +42 -0
  132. amsdal/schemas/mixins/verify_schemas_mixin.py +96 -0
  133. amsdal/schemas/mixins/verify_schemas_mixin.pyi +33 -0
  134. amsdal/schemas/repository.py +84 -0
  135. amsdal/schemas/repository.pyi +22 -0
  136. amsdal/schemas/utils.py +16 -0
  137. amsdal/schemas/utils.pyi +10 -0
  138. amsdal/services/__init__.cpython-311-darwin.so +0 -0
  139. amsdal/services/transaction_execution.cpython-311-darwin.so +0 -0
  140. amsdal/services/transaction_execution.pyi +1 -1
  141. amsdal/utils/rollback/__init__.py +99 -54
  142. amsdal/utils/tests/helpers.py +185 -36
  143. {amsdal-0.3.5.dist-info → amsdal-0.4.0.dist-info}/METADATA +8 -8
  144. {amsdal-0.3.5.dist-info → amsdal-0.4.0.dist-info}/RECORD +150 -142
  145. {amsdal-0.3.5.dist-info → amsdal-0.4.0.dist-info}/WHEEL +1 -1
  146. amsdal/contrib/auth/models/login_session/hooks/pre_init.py +0 -68
  147. amsdal/contrib/auth/models/login_session/model.json +0 -23
  148. amsdal/contrib/auth/models/login_session/modifiers/display_name.py +0 -11
  149. amsdal/contrib/auth/models/permission/fixtures/basic_permissions.json +0 -62
  150. amsdal/contrib/auth/models/permission/model.json +0 -18
  151. amsdal/contrib/auth/models/permission/modifiers/display_name.py +0 -11
  152. amsdal/contrib/auth/models/user/hooks/post_init.py +0 -76
  153. amsdal/contrib/auth/models/user/hooks/pre_create.py +0 -8
  154. amsdal/contrib/auth/models/user/model.json +0 -25
  155. amsdal/contrib/auth/models/user/modifiers/display_name.py +0 -19
  156. amsdal/contrib/frontend_configs/models/frontend_activator_config/model.json +0 -11
  157. amsdal/contrib/frontend_configs/models/frontend_config_async_validator/model.json +0 -11
  158. amsdal/contrib/frontend_configs/models/frontend_config_group_validator/model.json +0 -52
  159. amsdal/contrib/frontend_configs/models/frontend_config_option/model.json +0 -15
  160. amsdal/contrib/frontend_configs/models/frontend_config_skip_none_base/model.json +0 -6
  161. amsdal/contrib/frontend_configs/models/frontend_config_skip_none_base/properties/model_dump.py +0 -13
  162. amsdal/contrib/frontend_configs/models/frontend_config_slider_option/model.json +0 -19
  163. amsdal/contrib/frontend_configs/models/frontend_config_text_mask/model.json +0 -26
  164. amsdal/contrib/frontend_configs/models/frontend_config_validator/model.json +0 -41
  165. amsdal/contrib/frontend_configs/models/frontend_control_config/model.json +0 -250
  166. amsdal/contrib/frontend_configs/models/frontend_model_config/fixtures/permissions.json +0 -24
  167. amsdal/contrib/frontend_configs/models/frontend_model_config/model.json +0 -17
  168. amsdal/contrib/frontend_configs/models/frontent_config_control_action/model.json +0 -54
  169. amsdal/contrib/frontend_configs/models/frontent_config_control_action/properties/action_validate.py +0 -33
  170. amsdal/migration/__init__.cpython-311-darwin.so +0 -0
  171. amsdal/migration/base_migration_schemas.cpython-311-darwin.so +0 -0
  172. amsdal/migration/base_migration_schemas.pyi +0 -120
  173. amsdal/migration/data_classes.cpython-311-darwin.so +0 -0
  174. amsdal/migration/data_classes.pyi +0 -172
  175. amsdal/migration/executors/__init__.cpython-311-darwin.so +0 -0
  176. amsdal/migration/executors/base.cpython-311-darwin.so +0 -0
  177. amsdal/migration/executors/base.pyi +0 -118
  178. amsdal/migration/executors/default_executor.cpython-311-darwin.so +0 -0
  179. amsdal/migration/executors/default_executor.pyi +0 -184
  180. amsdal/migration/executors/state_executor.cpython-311-darwin.so +0 -0
  181. amsdal/migration/executors/state_executor.pyi +0 -151
  182. amsdal/migration/file_migration_executor.cpython-311-darwin.so +0 -0
  183. amsdal/migration/file_migration_executor.pyi +0 -122
  184. amsdal/migration/file_migration_generator.cpython-311-darwin.so +0 -0
  185. amsdal/migration/file_migration_generator.pyi +0 -229
  186. amsdal/migration/file_migration_store.cpython-311-darwin.so +0 -0
  187. amsdal/migration/file_migration_store.pyi +0 -114
  188. amsdal/migration/file_migration_writer.cpython-311-darwin.so +0 -0
  189. amsdal/migration/file_migration_writer.pyi +0 -73
  190. amsdal/migration/migrations.cpython-311-darwin.so +0 -0
  191. amsdal/migration/migrations.pyi +0 -166
  192. amsdal/migration/migrations_loader.cpython-311-darwin.so +0 -0
  193. amsdal/migration/migrations_loader.pyi +0 -32
  194. amsdal/migration/schemas_loaders.cpython-311-darwin.so +0 -0
  195. amsdal/migration/schemas_loaders.pyi +0 -37
  196. amsdal/migration/templates/data_migration.tmpl +0 -18
  197. amsdal/migration/templates/dict_validator.tmpl +0 -4
  198. amsdal/migration/templates/migration.tmpl +0 -6
  199. amsdal/migration/templates/model_class.tmpl +0 -8
  200. amsdal/migration/templates/model_class_layout.tmpl +0 -24
  201. amsdal/migration/templates/options_validator.tmpl +0 -4
  202. amsdal/migration/utils.cpython-311-darwin.so +0 -0
  203. amsdal/migration/utils.pyi +0 -58
  204. amsdal/mixins/build_mixin.cpython-311-darwin.so +0 -0
  205. amsdal/mixins/build_mixin.pyi +0 -78
  206. /amsdal/{migration/__init__.pyi → contrib/auth/models/__init__.py} +0 -0
  207. /amsdal/{migration/executors → contrib/auth/models}/__init__.pyi +0 -0
  208. {amsdal-0.3.5.dist-info → amsdal-0.4.0.dist-info}/LICENSE.txt +0 -0
  209. {amsdal-0.3.5.dist-info → amsdal-0.4.0.dist-info}/licenses/LICENSE.txt +0 -0
  210. {amsdal-0.3.5.dist-info → amsdal-0.4.0.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ from amsdal_data.application import DataApplication
4
4
  from amsdal_data.transactions.decorators import async_transaction
5
5
  from amsdal_data.transactions.decorators import transaction
6
6
  from amsdal_data.transactions.errors import AmsdalTransactionError
7
- from amsdal_models.classes.manager import ClassManager
7
+ from amsdal_models.classes.class_manager import ClassManager
8
8
  from amsdal_models.querysets.executor import LAKEHOUSE_DB_ALIAS
9
9
 
10
10
 
@@ -28,14 +28,21 @@ def rollback_to_timestamp(timestamp: float) -> None:
28
28
  table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
29
29
  where=glue.Conditions(
30
30
  glue.Condition(
31
- field=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
31
+ left=glue.FieldReferenceExpression(
32
+ field_reference=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
33
+ ),
32
34
  lookup=glue.FieldLookup.GT,
33
- value=glue.Value(timestamp),
35
+ right=glue.Value(timestamp),
34
36
  ),
35
37
  glue.Condition(
36
- field=glue.FieldReference(field=glue.Field(name='prior_version'), table_name='Metadata'),
38
+ left=glue.FieldReferenceExpression(
39
+ field_reference=glue.FieldReference(
40
+ field=glue.Field(name='prior_version'),
41
+ table_name='Metadata',
42
+ ),
43
+ ),
37
44
  lookup=glue.FieldLookup.ISNULL,
38
- value=glue.Value(True),
45
+ right=glue.Value(True),
39
46
  ),
40
47
  ),
41
48
  )
@@ -48,14 +55,21 @@ def rollback_to_timestamp(timestamp: float) -> None:
48
55
  table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
49
56
  where=glue.Conditions(
50
57
  glue.Condition(
51
- field=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
58
+ left=glue.FieldReferenceExpression(
59
+ field_reference=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
60
+ ),
52
61
  lookup=glue.FieldLookup.GT,
53
- value=glue.Value(timestamp),
62
+ right=glue.Value(timestamp),
54
63
  ),
55
64
  glue.Condition(
56
- field=glue.FieldReference(field=glue.Field(name='prior_version'), table_name='Metadata'),
65
+ left=glue.FieldReferenceExpression(
66
+ field_reference=glue.FieldReference(
67
+ field=glue.Field(name='prior_version'),
68
+ table_name='Metadata',
69
+ ),
70
+ ),
57
71
  lookup=glue.FieldLookup.ISNULL,
58
- value=glue.Value(False),
72
+ right=glue.Value(False),
59
73
  ),
60
74
  ),
61
75
  )
@@ -83,9 +97,12 @@ def rollback_to_timestamp(timestamp: float) -> None:
83
97
  _parent_field.child.child.parent = _parent_field.child # type: ignore[union-attr]
84
98
  _conditions.append(
85
99
  glue.Condition(
86
- field=glue.FieldReference(field=_parent_field, table_name='Metadata'),
100
+ left=glue.FieldReferenceExpression(
101
+ field_reference=glue.FieldReference(field=_parent_field, table_name='Metadata'),
102
+ output_type=str,
103
+ ),
87
104
  lookup=glue.FieldLookup.EQ,
88
- value=glue.Value(transaction_id),
105
+ right=glue.Value(transaction_id, output_type=str),
89
106
  )
90
107
  )
91
108
 
@@ -94,9 +111,14 @@ def rollback_to_timestamp(timestamp: float) -> None:
94
111
  table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
95
112
  where=glue.Conditions(
96
113
  glue.Condition(
97
- field=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
114
+ left=glue.FieldReferenceExpression(
115
+ field_reference=glue.FieldReference(
116
+ field=glue.Field(name='updated_at'),
117
+ table_name='Metadata',
118
+ ),
119
+ ),
98
120
  lookup=glue.FieldLookup.LTE,
99
- value=glue.Value(timestamp),
121
+ right=glue.Value(timestamp),
100
122
  ),
101
123
  glue.Conditions(*_conditions, connector=glue.FilterConnector.OR),
102
124
  ),
@@ -108,9 +130,7 @@ def rollback_to_timestamp(timestamp: float) -> None:
108
130
 
109
131
  for m in metadatas_to_delete:
110
132
  class_name = m.data['class_schema_reference']['ref']['object_id']
111
- schema_type = class_manager.resolve_schema_type(class_name)
112
-
113
- model_class = class_manager.import_model_class(class_name, schema_type)
133
+ model_class = class_manager.import_class(class_name)
114
134
  obj = (
115
135
  model_class.objects.filter(_address__object_id=m.data['object_id'])
116
136
  .using(LAKEHOUSE_DB_ALIAS)
@@ -123,8 +143,7 @@ def rollback_to_timestamp(timestamp: float) -> None:
123
143
  obj.delete()
124
144
 
125
145
  for object_id, class_name in ids_to_revert:
126
- schema_type = class_manager.resolve_schema_type(class_name)
127
- model_class = class_manager.import_model_class(class_name, schema_type)
146
+ model_class = class_manager.import_class(class_name)
128
147
 
129
148
  obj = (
130
149
  model_class.objects.filter(_address__object_id=object_id)
@@ -133,13 +152,14 @@ def rollback_to_timestamp(timestamp: float) -> None:
133
152
  .first()
134
153
  .execute()
135
154
  )
136
- old_obj = (
137
- model_class.objects.filter(_address__object_id=object_id, _metadata__updated_at__lte=timestamp)
138
- .using(LAKEHOUSE_DB_ALIAS)
139
- .order_by('-_metadata__updated_at')
140
- .first()
141
- .execute()
142
- )
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
+ # )
143
163
 
144
164
  if obj and old_obj:
145
165
  for field, value in old_obj.model_dump().items():
@@ -180,9 +200,12 @@ def rollback_transaction(transaction_id: str) -> None:
180
200
  table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
181
201
  where=glue.Conditions(
182
202
  glue.Condition(
183
- field=glue.FieldReference(field=_parent_field, table_name='Metadata'),
203
+ left=glue.FieldReferenceExpression(
204
+ field_reference=glue.FieldReference(field=_parent_field, table_name='Metadata'),
205
+ output_type=str,
206
+ ),
184
207
  lookup=glue.FieldLookup.EQ,
185
- value=glue.Value(transaction_id),
208
+ right=glue.Value(transaction_id, output_type=str),
186
209
  )
187
210
  ),
188
211
  order_by=[
@@ -222,14 +245,21 @@ async def async_rollback_to_timestamp(timestamp: float) -> None:
222
245
  table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
223
246
  where=glue.Conditions(
224
247
  glue.Condition(
225
- field=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
248
+ left=glue.FieldReferenceExpression(
249
+ field_reference=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
250
+ ),
226
251
  lookup=glue.FieldLookup.GT,
227
- value=glue.Value(timestamp),
252
+ right=glue.Value(timestamp),
228
253
  ),
229
254
  glue.Condition(
230
- field=glue.FieldReference(field=glue.Field(name='prior_version'), table_name='Metadata'),
255
+ left=glue.FieldReferenceExpression(
256
+ field_reference=glue.FieldReference(
257
+ field=glue.Field(name='prior_version'),
258
+ table_name='Metadata',
259
+ ),
260
+ ),
231
261
  lookup=glue.FieldLookup.ISNULL,
232
- value=glue.Value(True),
262
+ right=glue.Value(True),
233
263
  ),
234
264
  ),
235
265
  )
@@ -242,14 +272,20 @@ async def async_rollback_to_timestamp(timestamp: float) -> None:
242
272
  table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
243
273
  where=glue.Conditions(
244
274
  glue.Condition(
245
- field=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
275
+ left=glue.FieldReferenceExpression(
276
+ field_reference=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
277
+ ),
246
278
  lookup=glue.FieldLookup.GT,
247
- value=glue.Value(timestamp),
279
+ right=glue.Value(timestamp),
248
280
  ),
249
281
  glue.Condition(
250
- field=glue.FieldReference(field=glue.Field(name='prior_version'), table_name='Metadata'),
282
+ left=glue.FieldReferenceExpression(
283
+ field_reference=glue.FieldReference(
284
+ field=glue.Field(name='prior_version'), table_name='Metadata'
285
+ ),
286
+ ),
251
287
  lookup=glue.FieldLookup.ISNULL,
252
- value=glue.Value(False),
288
+ right=glue.Value(False),
253
289
  ),
254
290
  ),
255
291
  )
@@ -277,9 +313,12 @@ async def async_rollback_to_timestamp(timestamp: float) -> None:
277
313
  _parent_field.child.child.parent = _parent_field.child # type: ignore[union-attr]
278
314
  _conditions.append(
279
315
  glue.Condition(
280
- field=glue.FieldReference(field=_parent_field, table_name='Metadata'),
316
+ left=glue.FieldReferenceExpression(
317
+ field_reference=glue.FieldReference(field=_parent_field, table_name='Metadata'),
318
+ output_type=str,
319
+ ),
281
320
  lookup=glue.FieldLookup.EQ,
282
- value=glue.Value(transaction_id),
321
+ right=glue.Value(transaction_id, output_type=str),
283
322
  )
284
323
  )
285
324
 
@@ -288,9 +327,14 @@ async def async_rollback_to_timestamp(timestamp: float) -> None:
288
327
  table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
289
328
  where=glue.Conditions(
290
329
  glue.Condition(
291
- field=glue.FieldReference(field=glue.Field(name='updated_at'), table_name='Metadata'),
330
+ left=glue.FieldReferenceExpression(
331
+ field_reference=glue.FieldReference(
332
+ field=glue.Field(name='updated_at'),
333
+ table_name='Metadata',
334
+ ),
335
+ ),
292
336
  lookup=glue.FieldLookup.LTE,
293
- value=glue.Value(timestamp),
337
+ right=glue.Value(timestamp),
294
338
  ),
295
339
  glue.Conditions(*_conditions, connector=glue.FilterConnector.OR),
296
340
  ),
@@ -302,9 +346,7 @@ async def async_rollback_to_timestamp(timestamp: float) -> None:
302
346
 
303
347
  for m in metadatas_to_delete:
304
348
  class_name = m.data['class_schema_reference']['ref']['object_id']
305
- schema_type = class_manager.resolve_schema_type(class_name)
306
-
307
- model_class = class_manager.import_model_class(class_name, schema_type)
349
+ model_class = class_manager.import_class(class_name)
308
350
  obj = await (
309
351
  model_class.objects.filter(_address__object_id=m.data['object_id'])
310
352
  .using(LAKEHOUSE_DB_ALIAS)
@@ -317,8 +359,7 @@ async def async_rollback_to_timestamp(timestamp: float) -> None:
317
359
  await obj.adelete()
318
360
 
319
361
  for object_id, class_name in ids_to_revert:
320
- schema_type = class_manager.resolve_schema_type(class_name)
321
- model_class = class_manager.import_model_class(class_name, schema_type)
362
+ model_class = class_manager.import_class(class_name)
322
363
 
323
364
  obj = await (
324
365
  model_class.objects.filter(_address__object_id=object_id)
@@ -327,16 +368,17 @@ async def async_rollback_to_timestamp(timestamp: float) -> None:
327
368
  .first()
328
369
  .aexecute()
329
370
  )
330
- old_obj = await (
331
- model_class.objects.filter(_address__object_id=object_id, _metadata__updated_at__lte=timestamp)
332
- .using(LAKEHOUSE_DB_ALIAS)
333
- .order_by('-_metadata__updated_at')
334
- .first()
335
- .aexecute()
336
- )
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
+ # )
337
379
 
338
380
  if obj and old_obj:
339
- for field, value in old_obj.model_dump().items():
381
+ for field, value in (await old_obj.amodel_dump()).items():
340
382
  setattr(obj, field, value)
341
383
 
342
384
  await obj.asave()
@@ -373,9 +415,12 @@ async def async_rollback_transaction(transaction_id: str) -> None:
373
415
  table=glue.SchemaReference(name='Metadata', version=glue.Version.LATEST),
374
416
  where=glue.Conditions(
375
417
  glue.Condition(
376
- field=glue.FieldReference(field=_parent_field, table_name='Metadata'),
418
+ left=glue.FieldReferenceExpression(
419
+ field_reference=glue.FieldReference(field=_parent_field, table_name='Metadata'),
420
+ output_type=str,
421
+ ),
377
422
  lookup=glue.FieldLookup.EQ,
378
- value=glue.Value(transaction_id),
423
+ right=glue.Value(transaction_id, output_type=str),
379
424
  )
380
425
  ),
381
426
  order_by=[
@@ -2,31 +2,36 @@ import os
2
2
  import random
3
3
  import string
4
4
  import tempfile
5
+ from collections.abc import AsyncGenerator
6
+ from collections.abc import AsyncIterator
5
7
  from collections.abc import Generator
6
8
  from collections.abc import Iterator
9
+ from contextlib import asynccontextmanager
7
10
  from contextlib import contextmanager
8
11
  from contextlib import suppress
9
12
  from pathlib import Path
10
13
  from typing import Any
11
14
 
12
15
  import yaml
16
+ from amsdal_data.application import AsyncDataApplication
17
+ from amsdal_models.migration import MigrationsLoader
18
+ from amsdal_models.migration import migrations
19
+ from amsdal_models.migration.executors.default_executor import DefaultAsyncMigrationExecutor
20
+ from amsdal_models.migration.executors.default_executor import DefaultMigrationExecutor
21
+ from amsdal_models.migration.file_migration_executor import FileMigrationExecutorManager
22
+ from amsdal_models.migration.file_migration_generator import FileMigrationGenerator
23
+ from amsdal_models.migration.file_migration_writer import FileMigrationWriter
24
+ from amsdal_models.migration.migrations import MigrateData
25
+ from amsdal_models.migration.migrations import MigrationSchemas
26
+ from amsdal_models.migration.schemas_loaders import JsonClassSchemaLoader # type: ignore
27
+ from amsdal_models.migration.utils import contrib_to_module_root_path
13
28
  from amsdal_utils.config.manager import AmsdalConfigManager
14
- from amsdal_utils.models.enums import SchemaTypes
29
+ from amsdal_utils.models.enums import ModuleType
15
30
 
16
31
  from amsdal.configs.constants import CORE_MIGRATIONS_PATH
17
32
  from amsdal.configs.main import settings
18
33
  from amsdal.manager import AmsdalManager
19
- from amsdal.migration import migrations
20
- from amsdal.migration.data_classes import ModuleTypes
21
- from amsdal.migration.executors.default_executor import DefaultMigrationExecutor
22
- from amsdal.migration.file_migration_executor import FileMigrationExecutorManager
23
- from amsdal.migration.file_migration_generator import FileMigrationGenerator
24
- from amsdal.migration.file_migration_writer import FileMigrationWriter
25
- from amsdal.migration.migrations import MigrateData
26
- from amsdal.migration.migrations import MigrationSchemas
27
- from amsdal.migration.migrations_loader import MigrationsLoader
28
- from amsdal.migration.schemas_loaders import JsonClassSchemaLoader
29
- from amsdal.migration.utils import contrib_to_module_root_path
34
+ from amsdal.manager import AsyncAmsdalManager
30
35
  from amsdal.utils.tests.enums import DbExecutionType
31
36
  from amsdal.utils.tests.enums import LakehouseOption
32
37
  from amsdal.utils.tests.enums import StateOption
@@ -89,19 +94,32 @@ def _get_config_template(
89
94
  db_execution_type: DbExecutionType,
90
95
  lakehouse_option: LakehouseOption,
91
96
  state_option: StateOption,
97
+ *,
98
+ is_async: bool = False,
92
99
  ) -> str:
93
100
  config_object: dict[str, Any] = {
94
101
  'application_name': 'test_client_app',
102
+ 'async_mode': is_async,
95
103
  'connections': [
96
- {'name': 'lock', 'backend': 'amsdal_data.lock.implementations.thread_lock.ThreadLock'},
104
+ {
105
+ 'name': 'lock',
106
+ 'backend': 'amsdal_data.lock.implementations.thread_lock.ThreadLock',
107
+ },
97
108
  ],
98
- 'resources_config': {'lakehouse': 'lakehouse', 'lock': 'lock', 'repository': {'default': 'state'}},
109
+ 'resources_config': {
110
+ 'lakehouse': 'lakehouse',
111
+ 'lock': 'lock',
112
+ 'repository': {'default': 'state'},
113
+ },
99
114
  }
100
- if lakehouse_option in [LakehouseOption.postgres, LakehouseOption.postgres_immutable]:
115
+ if lakehouse_option in [
116
+ LakehouseOption.postgres,
117
+ LakehouseOption.postgres_immutable,
118
+ ]:
101
119
  config_object['connections'].append(
102
120
  {
103
121
  'name': 'lakehouse',
104
- 'backend': 'postgres-historical',
122
+ 'backend': 'postgres-historical-async' if is_async else 'postgres-historical',
105
123
  'credentials': [
106
124
  {
107
125
  'db_host': '{{ db_host }}',
@@ -117,7 +135,7 @@ def _get_config_template(
117
135
  config_object['connections'].append(
118
136
  {
119
137
  'name': 'lakehouse',
120
- 'backend': 'sqlite-historical',
138
+ 'backend': 'sqlite-historical-async' if is_async else 'sqlite-historical',
121
139
  'credentials': [{'db_path': '{{ db_dir }}/sqlite_lakehouse.sqlite3'}],
122
140
  }
123
141
  )
@@ -131,7 +149,7 @@ def _get_config_template(
131
149
  config_object['connections'].append(
132
150
  {
133
151
  'name': 'state',
134
- 'backend': 'postgres',
152
+ 'backend': 'postgres-async' if is_async else 'postgres',
135
153
  'credentials': [
136
154
  {
137
155
  'db_host': '{{ db_host }}',
@@ -148,7 +166,7 @@ def _get_config_template(
148
166
  config_object['connections'].append(
149
167
  {
150
168
  'name': 'state',
151
- 'backend': 'sqlite',
169
+ 'backend': 'sqlite-async' if is_async else 'sqlite',
152
170
  'credentials': [{'db_path': '{{ db_dir }}/sqlite_state.sqlite3'}],
153
171
  }
154
172
  )
@@ -157,11 +175,13 @@ def _get_config_template(
157
175
 
158
176
 
159
177
  @contextmanager
160
- def init_manager(
178
+ def _init_manager(
161
179
  db_execution_type: DbExecutionType,
162
180
  lakehouse_option: LakehouseOption,
163
181
  state_option: StateOption,
164
- ) -> Generator[AmsdalManager, Any, None]:
182
+ *,
183
+ is_async: bool = False,
184
+ ) -> Generator[tuple[Path, Path], Any, None]:
165
185
  Path('.tmp').mkdir(exist_ok=True)
166
186
  with tempfile.TemporaryDirectory(dir='.tmp') as temp_dir:
167
187
  db_dir = Path(temp_dir) / 'db_dir'
@@ -169,9 +189,12 @@ def init_manager(
169
189
 
170
190
  lakehouse_database = ''.join(random.sample(string.ascii_letters, 16))
171
191
  state_database = ''.join(random.sample(string.ascii_letters, 16))
172
- config_text = _get_config_template(db_execution_type, lakehouse_option, state_option)
192
+ config_text = _get_config_template(db_execution_type, lakehouse_option, state_option, is_async=is_async)
173
193
 
174
- if lakehouse_option in [LakehouseOption.postgres, LakehouseOption.postgres_immutable]:
194
+ if lakehouse_option in [
195
+ LakehouseOption.postgres,
196
+ LakehouseOption.postgres_immutable,
197
+ ]:
175
198
  (
176
199
  db_host,
177
200
  db_port,
@@ -186,7 +209,10 @@ def init_manager(
186
209
  .replace('{{ db_password }}', db_password)
187
210
  .replace('{{ lakehouse_postgres_db }}', lakehouse_database)
188
211
  )
189
- elif lakehouse_option in [LakehouseOption.sqlite, LakehouseOption.sqlite_immutable]:
212
+ elif lakehouse_option in [
213
+ LakehouseOption.sqlite,
214
+ LakehouseOption.sqlite_immutable,
215
+ ]:
190
216
  config_text = config_text.replace('{{ db_dir }}', db_dir.absolute().as_posix())
191
217
 
192
218
  if state_option == StateOption.postgres:
@@ -204,6 +230,19 @@ def init_manager(
204
230
  config_path = Path(temp_dir) / 'config.yml'
205
231
  config_path.write_text(config_text)
206
232
 
233
+ yield db_dir, config_path
234
+
235
+
236
+ @contextmanager
237
+ def init_manager(
238
+ db_execution_type: DbExecutionType,
239
+ lakehouse_option: LakehouseOption,
240
+ state_option: StateOption,
241
+ ) -> Generator[AmsdalManager, Any, None]:
242
+ with _init_manager(db_execution_type, lakehouse_option, state_option) as (
243
+ db_dir,
244
+ config_path,
245
+ ):
207
246
  with override_settings(APP_PATH=db_dir, CONFIG_PATH=config_path):
208
247
  config_manager = AmsdalConfigManager()
209
248
  config_manager.load_config(config_path)
@@ -219,6 +258,83 @@ def init_manager(
219
258
  AmsdalConfigManager.invalidate()
220
259
 
221
260
 
261
+ @asynccontextmanager
262
+ async def async_init_manager(
263
+ db_execution_type: DbExecutionType,
264
+ lakehouse_option: LakehouseOption,
265
+ state_option: StateOption,
266
+ ) -> AsyncIterator[AsyncAmsdalManager]:
267
+ with _init_manager(db_execution_type, lakehouse_option, state_option, is_async=True) as (db_dir, config_path):
268
+ with override_settings(
269
+ APP_PATH=db_dir,
270
+ CONFIG_PATH=config_path,
271
+ ):
272
+ config_manager = AmsdalConfigManager()
273
+ config_manager.load_config(config_path)
274
+ manager = AsyncAmsdalManager()
275
+ await manager.setup()
276
+ await manager.post_setup() # type: ignore[call-arg,misc]
277
+
278
+ try:
279
+ yield manager
280
+ finally:
281
+ await manager.teardown()
282
+ await AsyncDataApplication().teardown()
283
+ AsyncAmsdalManager.invalidate()
284
+ AmsdalConfigManager.invalidate()
285
+ AsyncDataApplication.invalidate()
286
+
287
+
288
+ def migrate(app_schemas_path: Path) -> None:
289
+ schemas = MigrationSchemas()
290
+ executor = DefaultMigrationExecutor(schemas)
291
+ _migrate_per_loader(
292
+ executor,
293
+ MigrationsLoader(
294
+ migrations_dir=CORE_MIGRATIONS_PATH,
295
+ module_type=ModuleType.CORE,
296
+ ),
297
+ )
298
+
299
+ for contrib in settings.CONTRIBS:
300
+ contrib_root_path = contrib_to_module_root_path(contrib)
301
+ _migrate_per_loader(
302
+ executor,
303
+ MigrationsLoader(
304
+ migrations_dir=contrib_root_path / settings.MIGRATIONS_DIRECTORY_NAME,
305
+ module_type=ModuleType.CONTRIB,
306
+ module_name=contrib,
307
+ ),
308
+ )
309
+
310
+ schema_loader = JsonClassSchemaLoader(app_schemas_path)
311
+
312
+ for class_schema in schema_loader.iter_app_schemas():
313
+ for _operation_data in FileMigrationGenerator.build_operations(
314
+ ModuleType.USER,
315
+ class_schema.object_schema,
316
+ None,
317
+ ):
318
+ _operation_name = FileMigrationWriter.operation_name_map[_operation_data.type]
319
+ kwargs = {}
320
+
321
+ if _operation_data.old_schema:
322
+ kwargs['old_schema'] = _operation_data.old_schema.model_dump()
323
+
324
+ if _operation_data.new_schema:
325
+ kwargs['new_schema'] = _operation_data.new_schema.model_dump()
326
+
327
+ _operation = getattr(migrations, _operation_name)(
328
+ schema_type=ModuleType.USER,
329
+ class_name=_operation_data.class_name,
330
+ **kwargs,
331
+ )
332
+
333
+ _operation.forward(executor)
334
+
335
+ executor.flush_buffer()
336
+
337
+
222
338
  def _migrate_per_loader(executor: DefaultMigrationExecutor, loader: MigrationsLoader) -> None:
223
339
  for _migration in loader:
224
340
  migration_class = FileMigrationExecutorManager.get_migration_class(_migration)
@@ -233,24 +349,24 @@ def _migrate_per_loader(executor: DefaultMigrationExecutor, loader: MigrationsLo
233
349
  executor.flush_buffer()
234
350
 
235
351
 
236
- def migrate(app_schemas_path: Path) -> None:
352
+ async def async_migrate(app_schemas_path: Path) -> None:
237
353
  schemas = MigrationSchemas()
238
- executor = DefaultMigrationExecutor(schemas)
239
- _migrate_per_loader(
354
+ executor = DefaultAsyncMigrationExecutor(schemas)
355
+ await _async_migrate_per_loader(
240
356
  executor,
241
357
  MigrationsLoader(
242
358
  migrations_dir=CORE_MIGRATIONS_PATH,
243
- module_type=ModuleTypes.CORE,
359
+ module_type=ModuleType.CORE,
244
360
  ),
245
361
  )
246
362
 
247
363
  for contrib in settings.CONTRIBS:
248
364
  contrib_root_path = contrib_to_module_root_path(contrib)
249
- _migrate_per_loader(
365
+ await _async_migrate_per_loader(
250
366
  executor,
251
367
  MigrationsLoader(
252
368
  migrations_dir=contrib_root_path / settings.MIGRATIONS_DIRECTORY_NAME,
253
- module_type=ModuleTypes.CONTRIB,
369
+ module_type=ModuleType.CONTRIB,
254
370
  module_name=contrib,
255
371
  ),
256
372
  )
@@ -259,7 +375,7 @@ def migrate(app_schemas_path: Path) -> None:
259
375
 
260
376
  for class_schema in schema_loader.iter_app_schemas():
261
377
  for _operation_data in FileMigrationGenerator.build_operations(
262
- SchemaTypes.USER,
378
+ ModuleType.USER,
263
379
  class_schema.object_schema,
264
380
  None,
265
381
  ):
@@ -273,14 +389,28 @@ def migrate(app_schemas_path: Path) -> None:
273
389
  kwargs['new_schema'] = _operation_data.new_schema.model_dump()
274
390
 
275
391
  _operation = getattr(migrations, _operation_name)(
276
- schema_type=SchemaTypes.USER,
392
+ schema_type=ModuleType.USER,
277
393
  class_name=_operation_data.class_name,
278
394
  **kwargs,
279
395
  )
280
396
 
281
397
  _operation.forward(executor)
282
398
 
283
- executor.flush_buffer()
399
+ await executor.flush_buffer()
400
+
401
+
402
+ async def _async_migrate_per_loader(executor: DefaultAsyncMigrationExecutor, loader: MigrationsLoader) -> None:
403
+ for _migration in loader:
404
+ migration_class = FileMigrationExecutorManager.get_migration_class(_migration)
405
+ migration_class_instance = migration_class()
406
+
407
+ for _operation in migration_class_instance.operations:
408
+ if isinstance(_operation, MigrateData):
409
+ await executor.flush_buffer()
410
+
411
+ _operation.forward(executor)
412
+
413
+ await executor.flush_buffer()
284
414
 
285
415
 
286
416
  @contextmanager
@@ -294,16 +424,35 @@ def init_manager_and_migrate(
294
424
  lakehouse_option=lakehouse_option,
295
425
  state_option=state_option,
296
426
  ) as manager:
297
- app_schemas_path = TESTS_DIR / 'src' / 'models'
427
+ manager.authenticate()
428
+ migrate()
429
+ manager.init_classes()
430
+
431
+ yield manager
432
+
433
+
434
+ @asynccontextmanager
435
+ async def async_init_manager_and_migrate(
436
+ db_execution_type: DbExecutionType,
437
+ lakehouse_option: LakehouseOption,
438
+ state_option: StateOption,
439
+ ) -> AsyncGenerator[AsyncAmsdalManager, Any]:
440
+ async with async_init_manager(
441
+ db_execution_type=db_execution_type,
442
+ lakehouse_option=lakehouse_option,
443
+ state_option=state_option,
444
+ ) as manager:
445
+ src_dir_path = TESTS_DIR / 'src'
446
+ app_schemas_path = src_dir_path / 'models'
298
447
  manager.build(
299
448
  source_models_path=app_schemas_path,
300
449
  source_fixtures_path=app_schemas_path,
301
- source_transactions_path=app_schemas_path,
450
+ source_transactions_path=src_dir_path,
302
451
  source_static_files_path=app_schemas_path,
303
452
  source_migrations_path=app_schemas_path,
304
453
  )
305
454
  manager.authenticate()
306
- migrate(app_schemas_path)
455
+ await async_migrate(app_schemas_path)
307
456
  manager.init_classes()
308
457
 
309
458
  yield manager