gabriel / musehub public
env.py python
109 lines 3.3 KB
Raw
sha256:a34090cc4a394a78bd72cbbe34b08cc59525141e19135b6c0ab154f10611b9ef debug(push/stream): instrument O-frame decode path with INF… Sonnet 4.6 patch 122 days ago
1 """Alembic environment configuration for Muse."""
2 from __future__ import annotations
3
4 import asyncio
5 from logging.config import fileConfig
6
7 from sqlalchemy import pool
8 from sqlalchemy.engine import Connection
9 from sqlalchemy.ext.asyncio import async_engine_from_config
10
11 from alembic import context
12
13 # Import your models' Base
14 from musehub.db.database import Base
15 from musehub.db import models # noqa: F401 - Import to register models
16 from musehub.db import muse_cli_models # noqa: F401 - Register Muse CLI commit tables (retained for MuseHub)
17 from musehub.config import settings
18
19 # Alembic Config object
20 config = context.config
21
22 # Interpret the config file for Python logging
23 if config.config_file_name is not None:
24 fileConfig(config.config_file_name)
25
26 # Add your model's MetaData object here for 'autogenerate' support
27 target_metadata = Base.metadata
28
29 # Override sqlalchemy.url with the one from settings (required; no default password in repo)
30 if not settings.database_url:
31 raise RuntimeError(
32 "DATABASE_URL (or DB_PASSWORD with Docker Postgres) must be set for migrations. "
33 "set in .env or export before running alembic."
34 )
35 config.set_main_option(
36 "sqlalchemy.url",
37 settings.database_url.replace("+asyncpg", ""),
38 )
39
40
41 def run_migrations_offline() -> None:
42 """Run migrations in 'offline' mode.
43
44 This configures the context with just a URL
45 and not an Engine, though an Engine is acceptable
46 here as well. By skipping the Engine creation
47 we don't even need a DBAPI to be available.
48
49 Calls to context.execute() here emit the given string to the
50 script output.
51 """
52 url = config.get_main_option("sqlalchemy.url")
53 context.configure(
54 url=url,
55 target_metadata=target_metadata,
56 literal_binds=True,
57 dialect_opts={"paramstyle": "named"},
58 compare_type=True,
59 compare_server_default=True,
60 )
61
62 with context.begin_transaction():
63 context.run_migrations()
64
65
66 def do_run_migrations(connection: Connection) -> None:
67 """Run migrations with a connection."""
68 context.configure(
69 connection=connection,
70 target_metadata=target_metadata,
71 compare_type=True,
72 compare_server_default=True,
73 )
74
75 with context.begin_transaction():
76 context.run_migrations()
77
78
79 async def run_async_migrations() -> None:
80 """Run migrations in 'online' mode with async support."""
81 configuration = config.get_section(config.config_ini_section, {})
82
83 # The ini option (set above) has +asyncpg stripped for the offline/sync
84 # autogenerate path. The async engine requires the full async URL, so we
85 # always override with settings.database_url here. Test isolation is
86 # handled by test fixtures that patch settings.database_url directly.
87 configuration["sqlalchemy.url"] = settings.database_url
88
89 connectable = async_engine_from_config(
90 configuration,
91 prefix="sqlalchemy.",
92 poolclass=pool.NullPool,
93 )
94
95 async with connectable.connect() as connection:
96 await connection.run_sync(do_run_migrations)
97
98 await connectable.dispose()
99
100
101 def run_migrations_online() -> None:
102 """Run migrations in 'online' mode."""
103 asyncio.run(run_async_migrations())
104
105
106 if context.is_offline_mode():
107 run_migrations_offline()
108 else:
109 run_migrations_online()
File History 1 commit
sha256:a34090cc4a394a78bd72cbbe34b08cc59525141e19135b6c0ab154f10611b9ef debug(push/stream): instrument O-frame decode path with INF… Sonnet 4.6 patch 122 days ago