lorebase-store 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. lorebase_store-0.2.3/.gitignore +79 -0
  2. lorebase_store-0.2.3/PKG-INFO +13 -0
  3. lorebase_store-0.2.3/alembic.ini +41 -0
  4. lorebase_store-0.2.3/migrations/env.py +106 -0
  5. lorebase_store-0.2.3/migrations/script.py.mako +27 -0
  6. lorebase_store-0.2.3/migrations/versions/0001_initial_schema.py +1071 -0
  7. lorebase_store-0.2.3/migrations/versions/0002_merge_attempt_details.py +74 -0
  8. lorebase_store-0.2.3/migrations/versions/0003_webhooks.py +127 -0
  9. lorebase_store-0.2.3/migrations/versions/0004_defer_revision_references.py +38 -0
  10. lorebase_store-0.2.3/migrations/versions/0005_security_definer_reads.py +396 -0
  11. lorebase_store-0.2.3/migrations/versions/0006_api_key_usage.py +48 -0
  12. lorebase_store-0.2.3/migrations/versions/0007_document_extraction.py +154 -0
  13. lorebase_store-0.2.3/migrations/versions/0008_definer_argument_checks.py +178 -0
  14. lorebase_store-0.2.3/migrations/versions/0009_api_key_networks.py +33 -0
  15. lorebase_store-0.2.3/migrations/versions/0010_overlay_branches.py +582 -0
  16. lorebase_store-0.2.3/migrations/versions/0011_branch_scoped_search_index.py +229 -0
  17. lorebase_store-0.2.3/migrations/versions/0012_overlay_neighborhood_lookups.py +185 -0
  18. lorebase_store-0.2.3/migrations/versions/0013_web_sessions.py +72 -0
  19. lorebase_store-0.2.3/migrations/versions/0014_embedding_jobs.py +70 -0
  20. lorebase_store-0.2.3/migrations/versions/0015_append_only_audit_log.py +83 -0
  21. lorebase_store-0.2.3/migrations/versions/0016_sealed_webhook_keys.py +55 -0
  22. lorebase_store-0.2.3/migrations/versions/0017_background_branch_copies.py +77 -0
  23. lorebase_store-0.2.3/migrations/versions/0018_search_lexicon.py +477 -0
  24. lorebase_store-0.2.3/migrations/versions/0019_vault_bindings.py +56 -0
  25. lorebase_store-0.2.3/migrations/versions/0020_outbox_consumers.py +150 -0
  26. lorebase_store-0.2.3/migrations/versions/0021_schema_suggestions.py +114 -0
  27. lorebase_store-0.2.3/migrations/versions/0022_read_audit_and_shared_rate_limits.py +133 -0
  28. lorebase_store-0.2.3/migrations/versions/0023_agent_trace.py +96 -0
  29. lorebase_store-0.2.3/migrations/versions/0024_embedding_template_keys.py +205 -0
  30. lorebase_store-0.2.3/migrations/versions/0025_snapshot_refs.py +35 -0
  31. lorebase_store-0.2.3/migrations/versions/0026_plain_reverse_link_index.py +112 -0
  32. lorebase_store-0.2.3/migrations/versions/0027_vault_rotation_and_tombstones.py +145 -0
  33. lorebase_store-0.2.3/migrations/versions/0028_operation_deferred_events.py +71 -0
  34. lorebase_store-0.2.3/migrations/versions/0029_agent_trace_sessions.py +108 -0
  35. lorebase_store-0.2.3/migrations/versions/0030_path_fanout.py +31 -0
  36. lorebase_store-0.2.3/migrations/versions/0031_branch_builds.py +91 -0
  37. lorebase_store-0.2.3/migrations/versions/0032_lineage_revisions.py +35 -0
  38. lorebase_store-0.2.3/migrations/versions/0033_vault_moved_tokens.py +30 -0
  39. lorebase_store-0.2.3/migrations/versions/0034_inference_endpoint_modes.py +73 -0
  40. lorebase_store-0.2.3/migrations/versions/0035_search_truncation.py +104 -0
  41. lorebase_store-0.2.3/migrations/versions/0036_lineage_maps.py +325 -0
  42. lorebase_store-0.2.3/migrations/versions/0037_bm25_search.py +346 -0
  43. lorebase_store-0.2.3/pyproject.toml +29 -0
  44. lorebase_store-0.2.3/src/lorebase_store/__init__.py +1 -0
  45. lorebase_store-0.2.3/src/lorebase_store/auth/__init__.py +52 -0
  46. lorebase_store-0.2.3/src/lorebase_store/auth/api_keys.py +161 -0
  47. lorebase_store-0.2.3/src/lorebase_store/auth/audit.py +382 -0
  48. lorebase_store-0.2.3/src/lorebase_store/auth/checkpoints.py +185 -0
  49. lorebase_store-0.2.3/src/lorebase_store/auth/grants.py +161 -0
  50. lorebase_store-0.2.3/src/lorebase_store/auth/principals.py +158 -0
  51. lorebase_store-0.2.3/src/lorebase_store/auth/scope.py +70 -0
  52. lorebase_store-0.2.3/src/lorebase_store/auth/sessions.py +153 -0
  53. lorebase_store-0.2.3/src/lorebase_store/auth/unit.py +53 -0
  54. lorebase_store-0.2.3/src/lorebase_store/auth/usage.py +70 -0
  55. lorebase_store-0.2.3/src/lorebase_store/blobs.py +73 -0
  56. lorebase_store-0.2.3/src/lorebase_store/bm25.py +346 -0
  57. lorebase_store-0.2.3/src/lorebase_store/bulk.py +147 -0
  58. lorebase_store-0.2.3/src/lorebase_store/bundle.py +1830 -0
  59. lorebase_store-0.2.3/src/lorebase_store/changefeed.py +261 -0
  60. lorebase_store-0.2.3/src/lorebase_store/commit/__init__.py +42 -0
  61. lorebase_store-0.2.3/src/lorebase_store/commit/changes.py +67 -0
  62. lorebase_store-0.2.3/src/lorebase_store/commit/errors.py +60 -0
  63. lorebase_store-0.2.3/src/lorebase_store/commit/migrations.py +335 -0
  64. lorebase_store-0.2.3/src/lorebase_store/commit/pipeline.py +754 -0
  65. lorebase_store-0.2.3/src/lorebase_store/commit/schema.py +123 -0
  66. lorebase_store-0.2.3/src/lorebase_store/db.py +58 -0
  67. lorebase_store-0.2.3/src/lorebase_store/definer.py +50 -0
  68. lorebase_store-0.2.3/src/lorebase_store/digests.py +99 -0
  69. lorebase_store-0.2.3/src/lorebase_store/embeddings.py +444 -0
  70. lorebase_store-0.2.3/src/lorebase_store/endpoint_modes.py +59 -0
  71. lorebase_store-0.2.3/src/lorebase_store/extraction/__init__.py +61 -0
  72. lorebase_store-0.2.3/src/lorebase_store/extraction/items.py +187 -0
  73. lorebase_store-0.2.3/src/lorebase_store/extraction/materialize.py +364 -0
  74. lorebase_store-0.2.3/src/lorebase_store/extraction/proposal.py +65 -0
  75. lorebase_store-0.2.3/src/lorebase_store/extraction/review.py +168 -0
  76. lorebase_store-0.2.3/src/lorebase_store/gc.py +970 -0
  77. lorebase_store-0.2.3/src/lorebase_store/indexes.py +1033 -0
  78. lorebase_store-0.2.3/src/lorebase_store/jobs.py +651 -0
  79. lorebase_store-0.2.3/src/lorebase_store/keyring.py +72 -0
  80. lorebase_store-0.2.3/src/lorebase_store/layout.py +335 -0
  81. lorebase_store-0.2.3/src/lorebase_store/materialize/__init__.py +103 -0
  82. lorebase_store-0.2.3/src/lorebase_store/materialize/apply.py +436 -0
  83. lorebase_store-0.2.3/src/lorebase_store/materialize/background.py +1184 -0
  84. lorebase_store-0.2.3/src/lorebase_store/materialize/branch.py +268 -0
  85. lorebase_store-0.2.3/src/lorebase_store/materialize/build.py +536 -0
  86. lorebase_store-0.2.3/src/lorebase_store/materialize/derived.py +540 -0
  87. lorebase_store-0.2.3/src/lorebase_store/materialize/lineage_backfill.py +502 -0
  88. lorebase_store-0.2.3/src/lorebase_store/materialize/links.py +266 -0
  89. lorebase_store-0.2.3/src/lorebase_store/materialize/overlay.py +292 -0
  90. lorebase_store-0.2.3/src/lorebase_store/materialize/paths.py +315 -0
  91. lorebase_store-0.2.3/src/lorebase_store/materialize/rebuild.py +326 -0
  92. lorebase_store-0.2.3/src/lorebase_store/materialize/rows.py +153 -0
  93. lorebase_store-0.2.3/src/lorebase_store/materialize/sensitivity.py +66 -0
  94. lorebase_store-0.2.3/src/lorebase_store/materialize/snapshot.py +205 -0
  95. lorebase_store-0.2.3/src/lorebase_store/materialize/stale.py +444 -0
  96. lorebase_store-0.2.3/src/lorebase_store/materialize/verify.py +321 -0
  97. lorebase_store-0.2.3/src/lorebase_store/merging/__init__.py +39 -0
  98. lorebase_store-0.2.3/src/lorebase_store/merging/attempts.py +334 -0
  99. lorebase_store-0.2.3/src/lorebase_store/merging/lineage.py +123 -0
  100. lorebase_store-0.2.3/src/lorebase_store/merging/service.py +652 -0
  101. lorebase_store-0.2.3/src/lorebase_store/migrations.py +133 -0
  102. lorebase_store-0.2.3/src/lorebase_store/models/__init__.py +136 -0
  103. lorebase_store-0.2.3/src/lorebase_store/models/base.py +64 -0
  104. lorebase_store-0.2.3/src/lorebase_store/models/enums.py +132 -0
  105. lorebase_store-0.2.3/src/lorebase_store/models/governance.py +268 -0
  106. lorebase_store-0.2.3/src/lorebase_store/models/ingestion.py +288 -0
  107. lorebase_store-0.2.3/src/lorebase_store/models/materialized.py +277 -0
  108. lorebase_store-0.2.3/src/lorebase_store/models/proposals.py +195 -0
  109. lorebase_store-0.2.3/src/lorebase_store/models/queues.py +87 -0
  110. lorebase_store-0.2.3/src/lorebase_store/models/tracing.py +116 -0
  111. lorebase_store-0.2.3/src/lorebase_store/models/versioning.py +222 -0
  112. lorebase_store-0.2.3/src/lorebase_store/models/webhooks.py +96 -0
  113. lorebase_store-0.2.3/src/lorebase_store/nodestore.py +384 -0
  114. lorebase_store-0.2.3/src/lorebase_store/objectstore.py +162 -0
  115. lorebase_store-0.2.3/src/lorebase_store/outbox_events.py +166 -0
  116. lorebase_store-0.2.3/src/lorebase_store/profiling/__init__.py +58 -0
  117. lorebase_store-0.2.3/src/lorebase_store/profiling/delimited.py +109 -0
  118. lorebase_store-0.2.3/src/lorebase_store/profiling/postgres.py +211 -0
  119. lorebase_store-0.2.3/src/lorebase_store/profiling/record_files.py +127 -0
  120. lorebase_store-0.2.3/src/lorebase_store/profiling/records.py +92 -0
  121. lorebase_store-0.2.3/src/lorebase_store/profiling/sql_databases.py +298 -0
  122. lorebase_store-0.2.3/src/lorebase_store/ratelimit.py +129 -0
  123. lorebase_store-0.2.3/src/lorebase_store/reads.py +1491 -0
  124. lorebase_store-0.2.3/src/lorebase_store/replicas.py +434 -0
  125. lorebase_store-0.2.3/src/lorebase_store/repositories/__init__.py +152 -0
  126. lorebase_store-0.2.3/src/lorebase_store/repositories/changesets.py +59 -0
  127. lorebase_store-0.2.3/src/lorebase_store/repositories/deferred_events.py +142 -0
  128. lorebase_store-0.2.3/src/lorebase_store/repositories/documents.py +305 -0
  129. lorebase_store-0.2.3/src/lorebase_store/repositories/domains.py +97 -0
  130. lorebase_store-0.2.3/src/lorebase_store/repositories/events.py +205 -0
  131. lorebase_store-0.2.3/src/lorebase_store/repositories/index_view.py +489 -0
  132. lorebase_store-0.2.3/src/lorebase_store/repositories/invocations.py +68 -0
  133. lorebase_store-0.2.3/src/lorebase_store/repositories/materializations.py +276 -0
  134. lorebase_store-0.2.3/src/lorebase_store/repositories/materialized.py +1129 -0
  135. lorebase_store-0.2.3/src/lorebase_store/repositories/merges.py +417 -0
  136. lorebase_store-0.2.3/src/lorebase_store/repositories/proposal_items.py +199 -0
  137. lorebase_store-0.2.3/src/lorebase_store/repositories/proposals.py +184 -0
  138. lorebase_store-0.2.3/src/lorebase_store/repositories/provenance.py +77 -0
  139. lorebase_store-0.2.3/src/lorebase_store/repositories/refs.py +452 -0
  140. lorebase_store-0.2.3/src/lorebase_store/repositories/revisions.py +273 -0
  141. lorebase_store-0.2.3/src/lorebase_store/repositories/scope.py +33 -0
  142. lorebase_store-0.2.3/src/lorebase_store/repositories/source_runs.py +123 -0
  143. lorebase_store-0.2.3/src/lorebase_store/repositories/suggestions.py +638 -0
  144. lorebase_store-0.2.3/src/lorebase_store/runtime.py +87 -0
  145. lorebase_store-0.2.3/src/lorebase_store/schema_cache.py +50 -0
  146. lorebase_store-0.2.3/src/lorebase_store/settings.py +879 -0
  147. lorebase_store-0.2.3/src/lorebase_store/storage.py +1478 -0
  148. lorebase_store-0.2.3/src/lorebase_store/telemetry.py +142 -0
  149. lorebase_store-0.2.3/src/lorebase_store/testing.py +108 -0
  150. lorebase_store-0.2.3/src/lorebase_store/tracing.py +505 -0
  151. lorebase_store-0.2.3/src/lorebase_store/traverse.py +578 -0
  152. lorebase_store-0.2.3/src/lorebase_store/vault/__init__.py +50 -0
  153. lorebase_store-0.2.3/src/lorebase_store/vault/keys.py +216 -0
  154. lorebase_store-0.2.3/src/lorebase_store/vault/quotes.py +133 -0
  155. lorebase_store-0.2.3/src/lorebase_store/vault/rotation.py +209 -0
  156. lorebase_store-0.2.3/src/lorebase_store/vault/settings.py +152 -0
  157. lorebase_store-0.2.3/src/lorebase_store/vault/store.py +987 -0
  158. lorebase_store-0.2.3/src/lorebase_store/vault/transfer.py +558 -0
  159. lorebase_store-0.2.3/src/lorebase_store/webhooks/__init__.py +24 -0
  160. lorebase_store-0.2.3/src/lorebase_store/webhooks/delivery.py +637 -0
  161. lorebase_store-0.2.3/src/lorebase_store/webhooks/keys.py +126 -0
  162. lorebase_store-0.2.3/src/lorebase_store/webhooks/repository.py +142 -0
  163. lorebase_store-0.2.3/src/lorebase_store/webhooks/settings.py +138 -0
  164. lorebase_store-0.2.3/src/lorebase_store/webhooks/signing.py +50 -0
  165. lorebase_store-0.2.3/tests/auth/conftest.py +51 -0
  166. lorebase_store-0.2.3/tests/auth/test_audit_append_only_integration.py +171 -0
  167. lorebase_store-0.2.3/tests/auth/test_audit_integration.py +257 -0
  168. lorebase_store-0.2.3/tests/auth/test_audit_streams_integration.py +109 -0
  169. lorebase_store-0.2.3/tests/auth/test_principals_api_keys_grants_integration.py +349 -0
  170. lorebase_store-0.2.3/tests/auth/test_rls_scope.py +47 -0
  171. lorebase_store-0.2.3/tests/auth/test_sessions_integration.py +135 -0
  172. lorebase_store-0.2.3/tests/conftest.py +74 -0
  173. lorebase_store-0.2.3/tests/read_support.py +230 -0
  174. lorebase_store-0.2.3/tests/support.py +192 -0
  175. lorebase_store-0.2.3/tests/test_background_branches.py +744 -0
  176. lorebase_store-0.2.3/tests/test_background_pace.py +50 -0
  177. lorebase_store-0.2.3/tests/test_bm25.py +111 -0
  178. lorebase_store-0.2.3/tests/test_bundle.py +419 -0
  179. lorebase_store-0.2.3/tests/test_bundle_limits.py +202 -0
  180. lorebase_store-0.2.3/tests/test_bundle_vault.py +172 -0
  181. lorebase_store-0.2.3/tests/test_bundle_vault_values.py +543 -0
  182. lorebase_store-0.2.3/tests/test_commit.py +488 -0
  183. lorebase_store-0.2.3/tests/test_commit_helpers.py +247 -0
  184. lorebase_store-0.2.3/tests/test_definer_checks.py +318 -0
  185. lorebase_store-0.2.3/tests/test_derived.py +114 -0
  186. lorebase_store-0.2.3/tests/test_endpoint_modes_integration.py +91 -0
  187. lorebase_store-0.2.3/tests/test_extraction_items.py +87 -0
  188. lorebase_store-0.2.3/tests/test_gc.py +562 -0
  189. lorebase_store-0.2.3/tests/test_indexes.py +815 -0
  190. lorebase_store-0.2.3/tests/test_jobs_depth.py +36 -0
  191. lorebase_store-0.2.3/tests/test_lineage_backfill.py +498 -0
  192. lorebase_store-0.2.3/tests/test_materialize.py +261 -0
  193. lorebase_store-0.2.3/tests/test_merging.py +333 -0
  194. lorebase_store-0.2.3/tests/test_migration_revisions.py +56 -0
  195. lorebase_store-0.2.3/tests/test_models.py +119 -0
  196. lorebase_store-0.2.3/tests/test_nodestore.py +199 -0
  197. lorebase_store-0.2.3/tests/test_outbox_events.py +108 -0
  198. lorebase_store-0.2.3/tests/test_outbox_integration.py +425 -0
  199. lorebase_store-0.2.3/tests/test_overlay.py +726 -0
  200. lorebase_store-0.2.3/tests/test_profiling.py +215 -0
  201. lorebase_store-0.2.3/tests/test_profiling_record_files.py +104 -0
  202. lorebase_store-0.2.3/tests/test_profiling_records.py +76 -0
  203. lorebase_store-0.2.3/tests/test_profiling_sql.py +331 -0
  204. lorebase_store-0.2.3/tests/test_ratelimit_buckets_integration.py +65 -0
  205. lorebase_store-0.2.3/tests/test_reads.py +917 -0
  206. lorebase_store-0.2.3/tests/test_replicas.py +414 -0
  207. lorebase_store-0.2.3/tests/test_repositories.py +390 -0
  208. lorebase_store-0.2.3/tests/test_schema_integration.py +288 -0
  209. lorebase_store-0.2.3/tests/test_search_bm25.py +458 -0
  210. lorebase_store-0.2.3/tests/test_sensitivity_refresh.py +402 -0
  211. lorebase_store-0.2.3/tests/test_settings.py +212 -0
  212. lorebase_store-0.2.3/tests/test_storage.py +561 -0
  213. lorebase_store-0.2.3/tests/test_suggestion_fold.py +178 -0
  214. lorebase_store-0.2.3/tests/test_suggestion_repository_integration.py +241 -0
  215. lorebase_store-0.2.3/tests/test_traverse.py +244 -0
  216. lorebase_store-0.2.3/tests/test_vault.py +785 -0
  217. lorebase_store-0.2.3/tests/test_webhook_keys.py +86 -0
  218. lorebase_store-0.2.3/tests/test_webhook_keys_integration.py +174 -0
  219. lorebase_store-0.2.3/tests/test_webhook_timeouts_integration.py +171 -0
  220. lorebase_store-0.2.3/tests/test_webhooks.py +308 -0
@@ -0,0 +1,79 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .eggs/
11
+ .venv/
12
+ venv/
13
+ .python-eggs/
14
+ pip-wheel-metadata/
15
+ .pytest_cache/
16
+ .mypy_cache/
17
+ .ruff_cache/
18
+ .pyre/
19
+ .pytype/
20
+ .hypothesis/
21
+ .coverage
22
+ .coverage.*
23
+ coverage.xml
24
+ htmlcov/
25
+ .tox/
26
+ .nox/
27
+ *.prof
28
+
29
+ # Node
30
+ node_modules/
31
+ .pnpm-store/
32
+ .npm/
33
+ .yarn/
34
+ !.yarn/releases
35
+ .pnp.*
36
+ npm-debug.log*
37
+ yarn-debug.log*
38
+ yarn-error.log*
39
+ pnpm-debug.log*
40
+ .vite/
41
+ *.tsbuildinfo
42
+ apps/web/dist/
43
+ apps/web/.vitest/
44
+
45
+ # Environment and secrets
46
+ .env
47
+ .env.*
48
+ !.env.example
49
+ *.pem
50
+ *.key
51
+ secrets/
52
+
53
+ # Docker
54
+ docker-compose.override.yaml
55
+ docker-compose.override.yml
56
+ .docker/
57
+
58
+ # Data and local artifacts
59
+ *.sqlite
60
+ *.db
61
+ /tmp/
62
+ /data/
63
+ tests/perf/results/
64
+
65
+ # Editors and OS
66
+ .idea/
67
+ .vscode/*
68
+ !.vscode/extensions.json
69
+ !.vscode/settings.example.json
70
+ *.swp
71
+ *.swo
72
+ *~
73
+ .DS_Store
74
+ Thumbs.db
75
+ *.code-workspace
76
+ .history/
77
+
78
+ # Session worktrees
79
+ .claude/
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.5
2
+ Name: lorebase-store
3
+ Version: 0.2.3
4
+ Summary: Lorebase store: persistence, repositories, migrations and materializer
5
+ Requires-Python: >=3.12
6
+ Requires-Dist: alembic>=1.13
7
+ Requires-Dist: asyncpg>=0.29
8
+ Requires-Dist: cryptography>=42
9
+ Requires-Dist: lorebase-core<0.3,>=0.2
10
+ Requires-Dist: lorebase-platform<0.3,>=0.2
11
+ Requires-Dist: opentelemetry-api>=1.25
12
+ Requires-Dist: pgvector>=0.3
13
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.30
@@ -0,0 +1,41 @@
1
+ # Alembic configuration for the Lorebase store. The database URL and every other value come
2
+ # from the `store` settings section (LOREBASE_CONFIG, LOREBASE__STORE__*), never from this file.
3
+ # Usage from the repository root: uv run alembic -c packages/store/alembic.ini upgrade head
4
+
5
+ [alembic]
6
+ script_location = %(here)s/migrations
7
+ path_separator = os
8
+
9
+ [loggers]
10
+ keys = root,sqlalchemy,alembic
11
+
12
+ [handlers]
13
+ keys = console
14
+
15
+ [formatters]
16
+ keys = generic
17
+
18
+ [logger_root]
19
+ level = WARNING
20
+ handlers = console
21
+ qualname =
22
+
23
+ [logger_sqlalchemy]
24
+ level = WARNING
25
+ handlers =
26
+ qualname = sqlalchemy.engine
27
+
28
+ [logger_alembic]
29
+ level = INFO
30
+ handlers =
31
+ qualname = alembic
32
+
33
+ [handler_console]
34
+ class = StreamHandler
35
+ args = (sys.stderr,)
36
+ level = NOTSET
37
+ formatter = generic
38
+
39
+ [formatter_generic]
40
+ format = %(levelname)-5.5s [%(name)s] %(message)s
41
+ datefmt = %H:%M:%S
@@ -0,0 +1,106 @@
1
+ """Alembic environment: async engine from the `database` section, layout from `store`.
2
+
3
+ `lorebase_store.migrations` may pass settings and a URL override through `config.attributes`;
4
+ anything missing (always, for `alembic upgrade head` on the command line) comes from
5
+ `load_settings()`, so `LOREBASE__DATABASE__DSN` and `LOREBASE_CONFIG` apply.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import asyncio
11
+ from logging.config import fileConfig
12
+ from typing import Any
13
+
14
+ from alembic import context
15
+ from alembic.migration import MigrationContext
16
+ from alembic.script import ScriptDirectory
17
+ from sqlalchemy.engine import Connection
18
+
19
+ from lorebase_platform.settings import load_settings
20
+ from lorebase_store.db import async_url, create_engine
21
+ from lorebase_store.migrations import (
22
+ DATABASE_ATTRIBUTE,
23
+ STORE_ATTRIBUTE,
24
+ URL_ATTRIBUTE,
25
+ check_known_revisions,
26
+ include_object,
27
+ )
28
+ from lorebase_store.models import metadata
29
+ from lorebase_store.settings import (
30
+ DatabaseSettings,
31
+ database_settings,
32
+ store_settings,
33
+ )
34
+
35
+ config = context.config
36
+ if config.config_file_name is not None:
37
+ fileConfig(config.config_file_name, disable_existing_loggers=False)
38
+
39
+ if DATABASE_ATTRIBUTE not in config.attributes or STORE_ATTRIBUTE not in config.attributes:
40
+ loaded = load_settings()
41
+ config.attributes.setdefault(DATABASE_ATTRIBUTE, database_settings(loaded))
42
+ config.attributes.setdefault(STORE_ATTRIBUTE, store_settings(loaded))
43
+ database: DatabaseSettings = config.attributes[DATABASE_ATTRIBUTE]
44
+ url: str = config.attributes.get(URL_ATTRIBUTE) or database.dsn.get_secret_value()
45
+
46
+
47
+ def _configure(**options: Any) -> None:
48
+ context.configure(
49
+ target_metadata=metadata,
50
+ include_object=include_object,
51
+ compare_type=True,
52
+ transaction_per_migration=True,
53
+ **options,
54
+ )
55
+
56
+
57
+ def run_offline() -> None:
58
+ """Emit SQL instead of executing it."""
59
+ _configure(
60
+ url=async_url(url).render_as_string(hide_password=False),
61
+ literal_binds=True,
62
+ dialect_opts={"paramstyle": "named"},
63
+ )
64
+ with context.begin_transaction():
65
+ context.run_migrations()
66
+
67
+
68
+ def _invoked_command() -> str | None:
69
+ """Name of the `alembic` command line command being run; None when called from code."""
70
+ invocation = getattr(config.cmd_opts, "cmd", None)
71
+ return getattr(invocation[0], "__name__", None) if invocation else None
72
+
73
+
74
+ def _run_sync(connection: Connection) -> None:
75
+ # `stamp --purge` is the manual way to repair the version table, so it is left alone.
76
+ if _invoked_command() != "stamp":
77
+ current = MigrationContext.configure(connection).get_current_heads()
78
+ # The read began a transaction; end it so that migrations manage their own (some run
79
+ # steps in autocommit blocks).
80
+ if connection.in_transaction():
81
+ connection.rollback()
82
+ check_known_revisions(ScriptDirectory.from_config(config), current)
83
+ _configure(connection=connection)
84
+ with context.begin_transaction():
85
+ context.run_migrations()
86
+
87
+
88
+ async def run_online() -> None:
89
+ """Run migrations on a dedicated, unpooled connection."""
90
+ engine = create_engine(
91
+ database,
92
+ url=url,
93
+ pooled=False,
94
+ statement_timeout_ms=database.migration_statement_timeout_ms,
95
+ )
96
+ try:
97
+ async with engine.connect() as connection:
98
+ await connection.run_sync(_run_sync)
99
+ finally:
100
+ await engine.dispose()
101
+
102
+
103
+ if context.is_offline_mode():
104
+ run_offline()
105
+ else:
106
+ asyncio.run(run_online())
@@ -0,0 +1,27 @@
1
+ """${message}
2
+
3
+ Revision ID: ${up_revision}
4
+ Revises: ${down_revision | comma,n}
5
+ Create Date: ${create_date}
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import Sequence
11
+
12
+ import sqlalchemy as sa
13
+ from alembic import op
14
+ ${imports if imports else ""}
15
+
16
+ revision: str = ${repr(up_revision)}
17
+ down_revision: str | Sequence[str] | None = ${repr(down_revision)}
18
+ branch_labels: str | Sequence[str] | None = ${repr(branch_labels)}
19
+ depends_on: str | Sequence[str] | None = ${repr(depends_on)}
20
+
21
+
22
+ def upgrade() -> None:
23
+ ${upgrades if upgrades else "pass"}
24
+
25
+
26
+ def downgrade() -> None:
27
+ ${downgrades if downgrades else "pass"}