amsdal 0.5.3__cp312-cp312-macosx_10_13_universal2.whl → 0.5.5__cp312-cp312-macosx_10_13_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.
Files changed (67) hide show
  1. amsdal/__about__.py +1 -1
  2. amsdal/cloud/__init__.cpython-312-darwin.so +0 -0
  3. amsdal/cloud/client.cpython-312-darwin.so +0 -0
  4. amsdal/cloud/constants.cpython-312-darwin.so +0 -0
  5. amsdal/cloud/enums.cpython-312-darwin.so +0 -0
  6. amsdal/cloud/models/__init__.cpython-312-darwin.so +0 -0
  7. amsdal/cloud/models/base.cpython-312-darwin.so +0 -0
  8. amsdal/cloud/services/__init__.cpython-312-darwin.so +0 -0
  9. amsdal/cloud/services/actions/__init__.cpython-312-darwin.so +0 -0
  10. amsdal/cloud/services/actions/add_allowlist_ip.cpython-312-darwin.so +0 -0
  11. amsdal/cloud/services/actions/add_basic_auth.cpython-312-darwin.so +0 -0
  12. amsdal/cloud/services/actions/add_dependency.cpython-312-darwin.so +0 -0
  13. amsdal/cloud/services/actions/add_secret.cpython-312-darwin.so +0 -0
  14. amsdal/cloud/services/actions/base.cpython-312-darwin.so +0 -0
  15. amsdal/cloud/services/actions/create_deploy.cpython-312-darwin.so +0 -0
  16. amsdal/cloud/services/actions/create_env.cpython-312-darwin.so +0 -0
  17. amsdal/cloud/services/actions/create_session.cpython-312-darwin.so +0 -0
  18. amsdal/cloud/services/actions/delete_allowlist_ip.cpython-312-darwin.so +0 -0
  19. amsdal/cloud/services/actions/delete_basic_auth.cpython-312-darwin.so +0 -0
  20. amsdal/cloud/services/actions/delete_dependency.cpython-312-darwin.so +0 -0
  21. amsdal/cloud/services/actions/delete_env.cpython-312-darwin.so +0 -0
  22. amsdal/cloud/services/actions/delete_secret.cpython-312-darwin.so +0 -0
  23. amsdal/cloud/services/actions/destroy_deploy.cpython-312-darwin.so +0 -0
  24. amsdal/cloud/services/actions/expose_db.cpython-312-darwin.so +0 -0
  25. amsdal/cloud/services/actions/get_basic_auth_credentials.cpython-312-darwin.so +0 -0
  26. amsdal/cloud/services/actions/get_monitoring_info.cpython-312-darwin.so +0 -0
  27. amsdal/cloud/services/actions/list_dependencies.cpython-312-darwin.so +0 -0
  28. amsdal/cloud/services/actions/list_deploys.cpython-312-darwin.so +0 -0
  29. amsdal/cloud/services/actions/list_envs.cpython-312-darwin.so +0 -0
  30. amsdal/cloud/services/actions/list_secrets.cpython-312-darwin.so +0 -0
  31. amsdal/cloud/services/actions/manager.cpython-312-darwin.so +0 -0
  32. amsdal/cloud/services/actions/signup_action.cpython-312-darwin.so +0 -0
  33. amsdal/cloud/services/actions/update_deploy.cpython-312-darwin.so +0 -0
  34. amsdal/cloud/services/auth/__init__.cpython-312-darwin.so +0 -0
  35. amsdal/cloud/services/auth/base.cpython-312-darwin.so +0 -0
  36. amsdal/cloud/services/auth/credentials.cpython-312-darwin.so +0 -0
  37. amsdal/cloud/services/auth/manager.cpython-312-darwin.so +0 -0
  38. amsdal/cloud/services/auth/signup_service.cpython-312-darwin.so +0 -0
  39. amsdal/cloud/services/auth/token.cpython-312-darwin.so +0 -0
  40. amsdal/contrib/__init__.cpython-312-darwin.so +0 -0
  41. amsdal/contrib/auth/lifecycle/consumer.pyi +1 -1
  42. amsdal/contrib/auth/models/login_session.pyi +4 -4
  43. amsdal/contrib/auth/models/permission.pyi +3 -3
  44. amsdal/contrib/auth/models/user.pyi +6 -5
  45. amsdal/contrib/frontend_configs/models/frontend_model_config.pyi +3 -3
  46. amsdal/fixtures/__init__.cpython-312-darwin.so +0 -0
  47. amsdal/fixtures/manager.cpython-312-darwin.so +0 -0
  48. amsdal/fixtures/manager.pyi +1 -1
  49. amsdal/fixtures/utils.cpython-312-darwin.so +0 -0
  50. amsdal/manager.cpython-312-darwin.so +0 -0
  51. amsdal/mixins/__init__.cpython-312-darwin.so +0 -0
  52. amsdal/mixins/class_versions_mixin.cpython-312-darwin.so +0 -0
  53. amsdal/models/core/class_object.pyi +8 -8
  54. amsdal/models/core/file.pyi +4 -4
  55. amsdal/models/core/fixture.pyi +6 -6
  56. amsdal/models/types/object.pyi +9 -9
  57. amsdal/schemas/manager.cpython-312-darwin.so +0 -0
  58. amsdal/services/__init__.cpython-312-darwin.so +0 -0
  59. amsdal/services/transaction_execution.cpython-312-darwin.so +0 -0
  60. amsdal/utils/tests/enums.py +0 -2
  61. amsdal/utils/tests/helpers.py +213 -381
  62. amsdal/utils/tests/migrations.py +179 -0
  63. {amsdal-0.5.3.dist-info → amsdal-0.5.5.dist-info}/METADATA +10 -6
  64. {amsdal-0.5.3.dist-info → amsdal-0.5.5.dist-info}/RECORD +67 -66
  65. {amsdal-0.5.3.dist-info → amsdal-0.5.5.dist-info}/WHEEL +0 -0
  66. {amsdal-0.5.3.dist-info → amsdal-0.5.5.dist-info}/licenses/LICENSE.txt +0 -0
  67. {amsdal-0.5.3.dist-info → amsdal-0.5.5.dist-info}/top_level.txt +0 -0
@@ -1,76 +1,55 @@
1
- import contextlib
2
- import os
3
1
  import random
4
2
  import string
5
- import tempfile
6
3
  from collections.abc import AsyncGenerator
7
4
  from collections.abc import AsyncIterator
8
5
  from collections.abc import Generator
9
6
  from collections.abc import Iterator
7
+ from contextlib import ExitStack
10
8
  from contextlib import asynccontextmanager
11
9
  from contextlib import contextmanager
12
- from contextlib import suppress
10
+ from functools import partial
13
11
  from pathlib import Path
14
12
  from typing import Any
15
13
 
16
- import yaml
14
+ from amsdal_data.aliases.db import POSTGRES_HISTORICAL_ALIAS
15
+ from amsdal_data.aliases.db import POSTGRES_HISTORICAL_ASYNC_ALIAS
16
+ from amsdal_data.aliases.db import POSTGRES_STATE_ALIAS
17
+ from amsdal_data.aliases.db import POSTGRES_STATE_ASYNC_ALIAS
18
+ from amsdal_data.aliases.db import SQLITE_ALIAS
19
+ from amsdal_data.aliases.db import SQLITE_ASYNC_ALIAS
20
+ from amsdal_data.aliases.db import SQLITE_HISTORICAL_ALIAS
21
+ from amsdal_data.aliases.db import SQLITE_HISTORICAL_ASYNC_ALIAS
17
22
  from amsdal_data.application import AsyncDataApplication
23
+ from amsdal_data.connections.db_alias_map import CONNECTION_BACKEND_ALIASES
18
24
  from amsdal_data.connections.historical.schema_version_manager import AsyncHistoricalSchemaVersionManager
19
25
  from amsdal_data.connections.historical.schema_version_manager import HistoricalSchemaVersionManager
20
- from amsdal_models.migration import migrations
21
- from amsdal_models.migration.executors.default_executor import DefaultAsyncMigrationExecutor
22
- from amsdal_models.migration.executors.default_executor import DefaultMigrationExecutor
23
- from amsdal_models.migration.file_migration_executor import SimpleFileMigrationExecutorManager
24
- from amsdal_models.migration.file_migration_generator import SimpleFileMigrationGenerator
25
- from amsdal_models.migration.file_migration_writer import FileMigrationWriter
26
- from amsdal_models.migration.migrations import MigrateData
27
- from amsdal_models.migration.migrations import MigrationSchemas
28
- from amsdal_models.migration.migrations_loader import MigrationsLoader
29
- from amsdal_models.migration.utils import contrib_to_module_root_path
30
- from amsdal_models.schemas.class_schema_loader import ClassSchemaLoader
26
+ from amsdal_data.test_utils.common import temp_dir
27
+ from amsdal_data.test_utils.config import build_config
28
+ from amsdal_data.test_utils.config import postgres_async_config
29
+ from amsdal_data.test_utils.config import postgres_async_lakehouse_only_config
30
+ from amsdal_data.test_utils.config import postgres_config
31
+ from amsdal_data.test_utils.config import postgres_lakehouse_only_config
32
+ from amsdal_data.test_utils.config import sqlite_async_config
33
+ from amsdal_data.test_utils.config import sqlite_async_lakehouse_only_config
34
+ from amsdal_data.test_utils.config import sqlite_config
35
+ from amsdal_data.test_utils.config import sqlite_lakehouse_only_config
36
+ from amsdal_data.test_utils.constants import PG_TEST_HOST
37
+ from amsdal_data.test_utils.constants import PG_TEST_PASSWORD
38
+ from amsdal_data.test_utils.constants import PG_TEST_PORT
39
+ from amsdal_data.test_utils.constants import PG_TEST_USER
40
+ from amsdal_data.test_utils.db import create_postgres_database
41
+ from amsdal_data.test_utils.db import create_postgres_extension
42
+ from amsdal_data.test_utils.db import drop_postgres_database
43
+ from amsdal_utils.config.data_models.amsdal_config import AmsdalConfig
31
44
  from amsdal_utils.config.manager import AmsdalConfigManager
32
- from amsdal_utils.models.enums import ModuleType
33
45
 
34
- from amsdal.configs.constants import CORE_MIGRATIONS_PATH
35
- from amsdal.configs.main import settings
36
46
  from amsdal.manager import AmsdalManager
37
47
  from amsdal.manager import AsyncAmsdalManager
38
48
  from amsdal.utils.tests.enums import DbExecutionType
39
49
  from amsdal.utils.tests.enums import LakehouseOption
40
50
  from amsdal.utils.tests.enums import StateOption
41
-
42
- TESTS_DIR = Path(os.getcwd())
43
-
44
-
45
- def create_postgres_database(database: str) -> tuple[str, str, str, str]:
46
- import psycopg
47
-
48
- db_host = os.getenv('POSTGRES_HOST', 'localhost')
49
- db_port = os.getenv('POSTGRES_PORT', '5432')
50
- db_user = os.getenv('POSTGRES_USER', 'postgres')
51
- db_password = os.getenv('POSTGRES_PASSWORD', 'example')
52
-
53
- conn = psycopg.connect(
54
- host=db_host,
55
- port=db_port,
56
- user=db_user,
57
- password=db_password,
58
- autocommit=True,
59
- )
60
- cur = conn.cursor()
61
-
62
- with suppress(psycopg.errors.DuplicateDatabase):
63
- cur.execute(f'CREATE DATABASE "{database}"')
64
-
65
- cur.close()
66
- conn.close()
67
-
68
- return (
69
- db_host,
70
- db_port,
71
- db_user,
72
- db_password,
73
- )
51
+ from amsdal.utils.tests.migrations import async_migrate
52
+ from amsdal.utils.tests.migrations import migrate
74
53
 
75
54
 
76
55
  @contextmanager
@@ -93,147 +72,125 @@ def override_settings(**kwargs: Any) -> Iterator[None]:
93
72
  settings.override(**original_settings)
94
73
 
95
74
 
96
- def _get_config_template(
75
+ @contextmanager
76
+ def init_config(
97
77
  db_execution_type: DbExecutionType,
98
78
  lakehouse_option: LakehouseOption,
99
79
  state_option: StateOption,
100
80
  *,
101
81
  is_async: bool = False,
102
- ) -> str:
103
- config_object: dict[str, Any] = {
104
- 'application_name': 'test_client_app',
105
- 'async_mode': is_async,
106
- 'connections': [
107
- {
108
- 'name': 'lock',
109
- 'backend': 'amsdal_data.lock.implementations.thread_lock.ThreadLock',
110
- },
111
- ],
112
- 'resources_config': {
113
- 'lakehouse': 'lakehouse',
114
- 'lock': 'lock',
115
- 'repository': {'default': 'state'},
116
- },
117
- }
118
- if lakehouse_option in [
119
- LakehouseOption.postgres,
120
- LakehouseOption.postgres_immutable,
121
- ]:
122
- config_object['connections'].append(
123
- {
124
- 'name': 'lakehouse',
125
- 'backend': 'postgres-historical-async' if is_async else 'postgres-historical',
126
- 'credentials': [
127
- {
128
- 'db_host': '{{ db_host }}',
129
- 'db_port': '{{ db_port }}',
130
- 'db_user': '{{ db_user }}',
131
- 'db_password': '{{ db_password }}',
132
- 'db_name': '{{ lakehouse_postgres_db }}',
133
- }
134
- ],
135
- }
136
- )
137
- elif lakehouse_option in [LakehouseOption.sqlite, LakehouseOption.sqlite_immutable]:
138
- config_object['connections'].append(
139
- {
140
- 'name': 'lakehouse',
141
- 'backend': 'sqlite-historical-async' if is_async else 'sqlite-historical',
142
- 'credentials': [{'db_path': '{{ db_dir }}/sqlite_lakehouse.sqlite3'}],
143
- }
144
- )
82
+ db_name_prefix: str | None = None,
83
+ db_path: Path | None = None,
84
+ drop_database: bool = False,
85
+ ) -> Iterator[AmsdalConfig]:
86
+ if db_name_prefix:
87
+ lakehouse_database = f'{db_name_prefix}_lakehouse'
88
+ state_database = f'{db_name_prefix}_state'
89
+ else:
90
+ lakehouse_database = ''.join(random.sample(string.ascii_letters, 16))
91
+ state_database = ''.join(random.sample(string.ascii_letters, 16))
145
92
 
146
93
  if db_execution_type == DbExecutionType.lakehouse_only:
147
- config_object['resources_config']['repository']['default'] = 'lakehouse'
148
-
149
- return yaml.dump(config_object)
150
-
151
- if state_option == StateOption.postgres:
152
- config_object['connections'].append(
153
- {
154
- 'name': 'state',
155
- 'backend': 'postgres-async' if is_async else 'postgres',
156
- 'credentials': [
157
- {
158
- 'db_host': '{{ db_host }}',
159
- 'db_port': '{{ db_port }}',
160
- 'db_user': '{{ db_user }}',
161
- 'db_password': '{{ db_password }}',
162
- 'db_name': '{{ state_postgres_db }}',
163
- }
164
- ],
165
- }
166
- )
94
+ ctx_managers = {
95
+ LakehouseOption.sqlite: (
96
+ partial(sqlite_async_lakehouse_only_config, db_path)
97
+ if is_async
98
+ else partial(sqlite_lakehouse_only_config, db_path)
99
+ ),
100
+ LakehouseOption.postgres: (
101
+ partial(postgres_async_lakehouse_only_config, lakehouse_database, drop_database=drop_database)
102
+ if is_async
103
+ else partial(postgres_lakehouse_only_config, lakehouse_database, drop_database=drop_database)
104
+ ),
105
+ }
106
+ with ctx_managers[lakehouse_option]() as _amsdal_config:
107
+ yield _amsdal_config
108
+ return
109
+
110
+ if lakehouse_option.value == state_option.value:
111
+ ctx_managers = {
112
+ LakehouseOption.sqlite: (
113
+ partial(
114
+ sqlite_async_config,
115
+ db_path=db_path,
116
+ )
117
+ if is_async
118
+ else partial(sqlite_config, db_path)
119
+ ),
120
+ LakehouseOption.postgres: (
121
+ partial(
122
+ postgres_async_config,
123
+ lakehouse_database=lakehouse_database,
124
+ state_database=state_database,
125
+ drop_database=drop_database,
126
+ )
127
+ if is_async
128
+ else partial(
129
+ postgres_config,
130
+ lakehouse_database=lakehouse_database,
131
+ state_database=state_database,
132
+ drop_database=drop_database,
133
+ )
134
+ ),
135
+ }
167
136
 
168
- elif state_option == StateOption.sqlite:
169
- config_object['connections'].append(
170
- {
171
- 'name': 'state',
172
- 'backend': 'sqlite-async' if is_async else 'sqlite',
173
- 'credentials': [{'db_path': '{{ db_dir }}/sqlite_state.sqlite3'}],
174
- }
175
- )
137
+ with ctx_managers[lakehouse_option]() as _amsdal_config:
138
+ yield _amsdal_config
139
+ return
176
140
 
177
- return yaml.dump(config_object)
141
+ with ExitStack() as stack:
142
+ db_path = db_path if db_path else stack.enter_context(temp_dir())
178
143
 
144
+ if lakehouse_option == LakehouseOption.postgres:
145
+ config = build_config(
146
+ lakehouse_backend=CONNECTION_BACKEND_ALIASES[
147
+ POSTGRES_HISTORICAL_ASYNC_ALIAS if is_async else POSTGRES_HISTORICAL_ALIAS
148
+ ],
149
+ lakehouse_credentials={
150
+ 'dsn': f'postgresql://{PG_TEST_USER}:{PG_TEST_PASSWORD}@{PG_TEST_HOST}:{PG_TEST_PORT}/{lakehouse_database}',
151
+ },
152
+ state_backend=CONNECTION_BACKEND_ALIASES[SQLITE_ASYNC_ALIAS if is_async else SQLITE_ALIAS],
153
+ state_credentials={
154
+ 'db_path': f'{db_path}/amsdal_state.sqlite3',
155
+ },
156
+ is_async_mode=is_async,
157
+ )
158
+ AmsdalConfigManager().set_config(config)
159
+ create_postgres_database(lakehouse_database)
160
+ create_postgres_extension(lakehouse_database, 'vector')
161
+ try:
162
+ yield config
163
+ finally:
164
+ AmsdalConfigManager.invalidate()
179
165
 
180
- @contextmanager
181
- def _init_manager(
182
- db_execution_type: DbExecutionType,
183
- lakehouse_option: LakehouseOption,
184
- state_option: StateOption,
185
- *,
186
- is_async: bool = False,
187
- ) -> Generator[tuple[Path, Path], Any, None]:
188
- Path('.tmp').mkdir(exist_ok=True)
189
- with tempfile.TemporaryDirectory(dir='.tmp') as temp_dir:
190
- db_dir = Path(temp_dir) / 'db_dir'
191
- (db_dir / 'warehouse').mkdir(exist_ok=True, parents=True)
166
+ if drop_database:
167
+ drop_postgres_database(lakehouse_database)
168
+ return
192
169
 
193
- lakehouse_database = ''.join(random.sample(string.ascii_letters, 16))
194
- state_database = ''.join(random.sample(string.ascii_letters, 16))
195
- config_text = _get_config_template(db_execution_type, lakehouse_option, state_option, is_async=is_async)
196
-
197
- if lakehouse_option in [
198
- LakehouseOption.postgres,
199
- LakehouseOption.postgres_immutable,
200
- ]:
201
- (
202
- db_host,
203
- db_port,
204
- db_user,
205
- db_password,
206
- ) = create_postgres_database(lakehouse_database)
207
-
208
- config_text = (
209
- config_text.replace('{{ db_host }}', db_host)
210
- .replace('{{ db_port }}', db_port)
211
- .replace('{{ db_user }}', db_user)
212
- .replace('{{ db_password }}', db_password)
213
- .replace('{{ lakehouse_postgres_db }}', lakehouse_database)
214
- )
215
- elif lakehouse_option in [
216
- LakehouseOption.sqlite,
217
- LakehouseOption.sqlite_immutable,
218
- ]:
219
- config_text = config_text.replace('{{ db_dir }}', db_dir.absolute().as_posix())
220
-
221
- if state_option == StateOption.postgres:
222
- create_postgres_database(state_database)
223
- config_text = (
224
- config_text.replace('{{ db_host }}', db_host)
225
- .replace('{{ db_port }}', db_port)
226
- .replace('{{ db_user }}', db_user)
227
- .replace('{{ db_password }}', db_password)
228
- .replace('{{ state_postgres_db }}', state_database)
229
- )
230
- elif state_option == StateOption.sqlite:
231
- config_text = config_text.replace('{{ db_dir }}', db_dir.absolute().as_posix())
170
+ config = build_config(
171
+ lakehouse_backend=CONNECTION_BACKEND_ALIASES[
172
+ SQLITE_HISTORICAL_ASYNC_ALIAS if is_async else SQLITE_HISTORICAL_ALIAS
173
+ ],
174
+ lakehouse_credentials={
175
+ 'db_path': f'{db_path}/amsdal_historical.sqlite3',
176
+ },
177
+ state_backend=CONNECTION_BACKEND_ALIASES[POSTGRES_STATE_ASYNC_ALIAS if is_async else POSTGRES_STATE_ALIAS],
178
+ state_credentials={
179
+ 'dsn': f'postgresql://{PG_TEST_USER}:{PG_TEST_PASSWORD}@{PG_TEST_HOST}:{PG_TEST_PORT}/{state_database}',
180
+ },
181
+ is_async_mode=True,
182
+ )
183
+ AmsdalConfigManager().set_config(config)
184
+ create_postgres_database(state_database)
185
+ create_postgres_extension(state_database, 'vector')
232
186
 
233
- config_path = Path(temp_dir) / 'config.yml'
234
- config_path.write_text(config_text)
187
+ try:
188
+ yield config
189
+ finally:
190
+ AmsdalConfigManager.invalidate()
235
191
 
236
- yield db_dir, config_path
192
+ if drop_database:
193
+ drop_postgres_database(state_database)
237
194
 
238
195
 
239
196
  @contextmanager
@@ -242,30 +199,38 @@ def init_manager(
242
199
  db_execution_type: DbExecutionType,
243
200
  lakehouse_option: LakehouseOption,
244
201
  state_option: StateOption,
245
- ) -> Generator[AmsdalManager, Any, None]:
246
- with _init_manager(db_execution_type, lakehouse_option, state_option) as (
247
- db_dir,
248
- config_path,
249
- ):
250
- with override_settings(
251
- APP_PATH=db_dir,
252
- CONFIG_PATH=config_path,
253
- USER_MODELS_MODULE_PATH=src_dir_path / 'models',
254
- TRANSACTIONS_MODULE_PATH=src_dir_path / 'transactions',
255
- FIXTURES_MODULE_PATH=src_dir_path / 'fixtures',
256
- ):
257
- config_manager = AmsdalConfigManager()
258
- config_manager.load_config(config_path)
259
- manager = AmsdalManager()
260
- manager.setup()
261
- manager.post_setup() # type: ignore[call-arg]
202
+ app_models_path: Path | None = None,
203
+ app_transactions_path: Path | None = None,
204
+ app_fixtures_path: Path | None = None,
205
+ **settings_options: Any,
206
+ ) -> Iterator[AmsdalManager]:
207
+ app_models_path = app_models_path or src_dir_path / 'models'
208
+ app_transactions_path = app_transactions_path or src_dir_path / 'transactions'
209
+ app_fixtures_path = app_fixtures_path or src_dir_path / 'fixtures'
210
+
211
+ with ExitStack() as stack:
212
+ tmp_dir = stack.enter_context(temp_dir())
213
+ stack.enter_context(init_config(db_execution_type, lakehouse_option, state_option))
214
+ stack.enter_context(
215
+ override_settings(
216
+ APP_PATH=tmp_dir,
217
+ USER_MODELS_MODULE_PATH=app_models_path,
218
+ TRANSACTIONS_MODULE_PATH=app_transactions_path,
219
+ FIXTURES_MODULE_PATH=app_fixtures_path,
220
+ **settings_options,
221
+ ),
222
+ )
262
223
 
263
- try:
264
- yield manager
265
- finally:
266
- manager.teardown()
267
- AmsdalManager.invalidate()
268
- AmsdalConfigManager.invalidate()
224
+ manager = AmsdalManager()
225
+ manager.setup()
226
+ manager.post_setup() # type: ignore[call-arg]
227
+
228
+ try:
229
+ yield manager
230
+ finally:
231
+ manager.teardown()
232
+ AmsdalManager.invalidate()
233
+ AsyncDataApplication.invalidate()
269
234
 
270
235
 
271
236
  @asynccontextmanager
@@ -274,189 +239,38 @@ async def async_init_manager(
274
239
  db_execution_type: DbExecutionType,
275
240
  lakehouse_option: LakehouseOption,
276
241
  state_option: StateOption,
242
+ app_models_path: Path | None = None,
243
+ app_transactions_path: Path | None = None,
244
+ app_fixtures_path: Path | None = None,
245
+ **settings_options: Any,
277
246
  ) -> AsyncIterator[AsyncAmsdalManager]:
278
- with _init_manager(db_execution_type, lakehouse_option, state_option, is_async=True) as (db_dir, config_path):
279
- with override_settings(
280
- APP_PATH=db_dir,
281
- CONFIG_PATH=config_path,
282
- USER_MODELS_MODULE_PATH=src_dir_path / 'models',
283
- TRANSACTIONS_MODULE_PATH=src_dir_path / 'transactions',
284
- FIXTURES_MODULE_PATH=src_dir_path / 'fixtures',
285
- ):
286
- config_manager = AmsdalConfigManager()
287
- config_manager.load_config(config_path)
288
- manager = AsyncAmsdalManager()
289
- await manager.setup()
290
- await manager.post_setup() # type: ignore[call-arg,misc]
291
-
292
- try:
293
- yield manager
294
- finally:
295
- await manager.teardown()
296
- await AsyncDataApplication().teardown()
297
- AsyncAmsdalManager.invalidate()
298
- AmsdalConfigManager.invalidate()
299
- AsyncDataApplication.invalidate()
300
-
301
-
302
- def migrate() -> None:
303
- schemas = MigrationSchemas()
304
- executor = DefaultMigrationExecutor(schemas, use_foreign_keys=True)
305
-
306
- with contextlib.suppress(Exception):
307
- HistoricalSchemaVersionManager().object_classes # noqa: B018
308
-
309
- _migrate_per_loader(
310
- executor,
311
- MigrationsLoader(
312
- migrations_dir=CORE_MIGRATIONS_PATH,
313
- module_type=ModuleType.CORE,
314
- ),
315
- )
316
-
317
- for contrib in settings.CONTRIBS:
318
- contrib_root_path = contrib_to_module_root_path(contrib)
319
- _migrate_per_loader(
320
- executor,
321
- MigrationsLoader(
322
- migrations_dir=contrib_root_path / settings.MIGRATIONS_DIRECTORY_NAME,
323
- module_type=ModuleType.CONTRIB,
324
- module_name=contrib,
325
- ),
326
- )
327
-
328
- user_schema_loader = ClassSchemaLoader(
329
- settings.USER_MODELS_MODULE,
330
- class_filter=lambda cls: cls.__module_type__ == ModuleType.USER,
331
- )
332
- _schemas, _cycle_schemas = user_schema_loader.load_sorted()
333
- _schemas_map = {_schema.title: _schema for _schema in _schemas}
334
-
335
- for object_schema in _schemas:
336
- for _operation_data in SimpleFileMigrationGenerator.build_operations(
337
- ModuleType.USER,
338
- object_schema,
339
- None,
340
- ):
341
- _operation_name = FileMigrationWriter.operation_name_map[_operation_data.type]
342
- _operation = getattr(migrations, _operation_name)(
343
- module_type=ModuleType.USER,
344
- class_name=_operation_data.class_name,
345
- new_schema=_operation_data.new_schema.model_dump(),
346
- )
347
-
348
- _operation.forward(executor)
349
-
350
- for object_schema in _cycle_schemas:
351
- for _operation_data in SimpleFileMigrationGenerator.build_operations(
352
- ModuleType.USER,
353
- object_schema,
354
- _schemas_map[object_schema.title],
355
- ):
356
- _operation_name = FileMigrationWriter.operation_name_map[_operation_data.type]
357
- _operation = getattr(migrations, _operation_name)(
358
- module_type=ModuleType.USER,
359
- class_name=_operation_data.class_name,
360
- new_schema=_operation_data.new_schema.model_dump(),
247
+ app_models_path = app_models_path or src_dir_path / 'models'
248
+ app_transactions_path = app_transactions_path or src_dir_path / 'transactions'
249
+ app_fixtures_path = app_fixtures_path or src_dir_path / 'fixtures'
250
+
251
+ with ExitStack() as stack:
252
+ tmp_dir = stack.enter_context(temp_dir())
253
+ stack.enter_context(init_config(db_execution_type, lakehouse_option, state_option, is_async=True))
254
+ stack.enter_context(
255
+ override_settings(
256
+ APP_PATH=tmp_dir,
257
+ USER_MODELS_MODULE_PATH=app_models_path,
258
+ TRANSACTIONS_MODULE_PATH=app_transactions_path,
259
+ FIXTURES_MODULE_PATH=app_fixtures_path,
260
+ **settings_options,
361
261
  )
362
-
363
- _operation.forward(executor)
364
-
365
- executor.flush_buffer()
366
-
367
-
368
- def _migrate_per_loader(executor: DefaultMigrationExecutor, loader: MigrationsLoader) -> None:
369
- for _migration in loader:
370
- migration_class = SimpleFileMigrationExecutorManager.get_migration_class(_migration)
371
- migration_class_instance = migration_class()
372
-
373
- for _operation in migration_class_instance.operations:
374
- if isinstance(_operation, MigrateData):
375
- executor.flush_buffer()
376
-
377
- _operation.forward(executor)
378
-
379
- executor.flush_buffer()
380
-
381
-
382
- async def async_migrate() -> None:
383
- schemas = MigrationSchemas()
384
- executor = DefaultAsyncMigrationExecutor(schemas)
385
-
386
- with contextlib.suppress(Exception):
387
- await AsyncHistoricalSchemaVersionManager().object_classes
388
-
389
- await _async_migrate_per_loader(
390
- executor,
391
- MigrationsLoader(
392
- migrations_dir=CORE_MIGRATIONS_PATH,
393
- module_type=ModuleType.CORE,
394
- ),
395
- )
396
-
397
- for contrib in settings.CONTRIBS:
398
- contrib_root_path = contrib_to_module_root_path(contrib)
399
- await _async_migrate_per_loader(
400
- executor,
401
- MigrationsLoader(
402
- migrations_dir=contrib_root_path / settings.MIGRATIONS_DIRECTORY_NAME,
403
- module_type=ModuleType.CONTRIB,
404
- module_name=contrib,
405
- ),
406
262
  )
263
+ manager = AsyncAmsdalManager()
264
+ await manager.setup()
265
+ await manager.post_setup() # type: ignore[call-arg,misc]
407
266
 
408
- user_schema_loader = ClassSchemaLoader(
409
- settings.USER_MODELS_MODULE,
410
- class_filter=lambda cls: cls.__module_type__ == ModuleType.USER,
411
- )
412
- _schemas, _cycle_schemas = user_schema_loader.load_sorted()
413
- _schemas_map = {_schema.title: _schema for _schema in _schemas}
414
-
415
- for object_schema in _schemas:
416
- for _operation_data in SimpleFileMigrationGenerator.build_operations(
417
- ModuleType.USER,
418
- object_schema,
419
- None,
420
- ):
421
- _operation_name = FileMigrationWriter.operation_name_map[_operation_data.type]
422
- _operation = getattr(migrations, _operation_name)(
423
- module_type=ModuleType.USER,
424
- class_name=_operation_data.class_name,
425
- new_schema=_operation_data.new_schema.model_dump(),
426
- )
427
-
428
- _operation.forward(executor)
429
-
430
- for object_schema in _cycle_schemas:
431
- for _operation_data in SimpleFileMigrationGenerator.build_operations(
432
- ModuleType.USER,
433
- object_schema,
434
- _schemas_map[object_schema.title],
435
- ):
436
- _operation_name = FileMigrationWriter.operation_name_map[_operation_data.type]
437
- _operation = getattr(migrations, _operation_name)(
438
- module_type=ModuleType.USER,
439
- class_name=_operation_data.class_name,
440
- new_schema=_operation_data.new_schema.model_dump(),
441
- )
442
-
443
- _operation.forward(executor)
444
-
445
- await executor.flush_buffer()
446
-
447
-
448
- async def _async_migrate_per_loader(executor: DefaultAsyncMigrationExecutor, loader: MigrationsLoader) -> None:
449
- for _migration in loader:
450
- migration_class = SimpleFileMigrationExecutorManager.get_migration_class(_migration)
451
- migration_class_instance = migration_class()
452
-
453
- for _operation in migration_class_instance.operations:
454
- if isinstance(_operation, MigrateData):
455
- await executor.flush_buffer()
456
-
457
- _operation.forward(executor)
458
-
459
- await executor.flush_buffer()
267
+ try:
268
+ yield manager
269
+ finally:
270
+ await manager.teardown()
271
+ await AsyncDataApplication().teardown()
272
+ AsyncAmsdalManager.invalidate()
273
+ AsyncDataApplication.invalidate()
460
274
 
461
275
 
462
276
  @contextmanager
@@ -465,16 +279,25 @@ def init_manager_and_migrate(
465
279
  db_execution_type: DbExecutionType,
466
280
  lakehouse_option: LakehouseOption,
467
281
  state_option: StateOption,
282
+ app_models_path: Path | None = None,
283
+ app_transactions_path: Path | None = None,
284
+ app_fixtures_path: Path | None = None,
285
+ **settings_options: Any,
468
286
  ) -> Generator[AmsdalManager, Any, None]:
469
287
  with init_manager(
470
288
  src_dir_path=src_dir_path,
471
289
  db_execution_type=db_execution_type,
472
290
  lakehouse_option=lakehouse_option,
473
291
  state_option=state_option,
292
+ app_models_path=app_models_path,
293
+ app_transactions_path=app_transactions_path,
294
+ app_fixtures_path=app_fixtures_path,
295
+ **settings_options,
474
296
  ) as manager:
475
297
  migrate()
476
298
  manager.authenticate()
477
299
  manager.init_classes()
300
+ HistoricalSchemaVersionManager()._cache_object_classes.clear()
478
301
 
479
302
  yield manager
480
303
 
@@ -485,15 +308,24 @@ async def async_init_manager_and_migrate(
485
308
  db_execution_type: DbExecutionType,
486
309
  lakehouse_option: LakehouseOption,
487
310
  state_option: StateOption,
311
+ app_models_path: Path | None = None,
312
+ app_transactions_path: Path | None = None,
313
+ app_fixtures_path: Path | None = None,
314
+ **settings_options: Any,
488
315
  ) -> AsyncGenerator[AsyncAmsdalManager, Any]:
489
316
  async with async_init_manager(
490
317
  src_dir_path=src_dir_path,
491
318
  db_execution_type=db_execution_type,
492
319
  lakehouse_option=lakehouse_option,
493
320
  state_option=state_option,
321
+ app_models_path=app_models_path,
322
+ app_transactions_path=app_transactions_path,
323
+ app_fixtures_path=app_fixtures_path,
324
+ **settings_options,
494
325
  ) as manager:
495
326
  await async_migrate()
496
327
  manager.authenticate()
497
328
  manager.init_classes()
329
+ AsyncHistoricalSchemaVersionManager()._cache_object_classes.clear()
498
330
 
499
331
  yield manager