1414if spec is None or spec .loader is None :
1515 print ("Alembic has not been installed. Please run 'pip install alembic' to install it." )
1616 exit (1 )
17-
17+
1818import alembic
1919from alembic import command
2020from alembic .config import Config as AlembicConfig
2121
2222
23- class _RobynMigrateConfig :
24- """Robyn migration configuration."""
25-
26- def __init__ (self , directory : str = 'migrations' , ** kwargs ):
27- self .directory = directory
28- self .kwargs = kwargs
29-
30-
3123class Config (AlembicConfig ):
3224 """Configuration for Robyn migrations."""
3325
@@ -52,54 +44,6 @@ def _get_template_path(self, template=None):
5244 return Path (template )
5345
5446
55- class Migrate :
56- """Robyn extension for database migrations using Alembic."""
57-
58- def __init__ (self , app = None , db = None , directory = 'migrations' , ** kwargs ):
59- """Initialize the extension.
60-
61- Args:
62- app: The Robyn application instance
63- db: The SQLAlchemy database instance
64- directory: Directory where migration files will be stored
65- **kwargs: Additional arguments to pass to Alembic
66- """
67- self .app = app
68- self .db = db
69- self .directory = directory
70- self .kwargs = kwargs
71-
72- if app is not None and db is not None :
73- self .init_app (app , db , directory , ** kwargs )
74-
75- def init_app (self , app , db = None , directory = None , ** kwargs ):
76- """Initialize the application with this extension.
77-
78- Args:
79- app: The Robyn application instance
80- db: The SQLAlchemy database instance
81- directory: Directory where migration files will be stored
82- **kwargs: Additional arguments to pass to Alembic
83- """
84- self .app = app
85- self .db = db
86- self .directory = directory or self .directory
87- self .kwargs = kwargs or self .kwargs
88-
89- # Register before_request handler to ensure database connection
90- @app .before_request ()
91- async def ensure_db_connection (request ):
92- # This could be used to ensure database connection is established
93- # or perform any pre-request database setup
94- pass
95-
96- # Register after_request handler to clean up database resources
97- @app .after_request ()
98- async def cleanup_db_resources (response ):
99- # This could be used to clean up database resources after request
100- return response
101-
102-
10347def catch_errors (f ):
10448 """Decorator to catch and handle errors."""
10549
@@ -163,7 +107,7 @@ def _auto_configure_migrations(directory: str, db_url: Optional[str] = None, mod
163107 f .write (content )
164108 print (f"Successfully configured the database URL: { db_url } " )
165109
166- # 配置 env.py
110+ # Configure env.py
167111 if model_path :
168112 env_py_path = os .path .join (directory , 'env.py' )
169113 if os .path .exists (env_py_path ):
@@ -196,6 +140,28 @@ def _auto_configure_migrations(directory: str, db_url: Optional[str] = None, mod
196140 print (f"Warning: Could not parse the model path { model_path } , please manually configure env.py" )
197141
198142
143+ def _special_configure_for_sqlite (directory : str , model_path : Optional [str ] = None ):
144+ # If the database is SQLite, must add render_as_batch=True in run_migrations_online() to avoid migration errors caused by SQLite's limited support for ALTER TABLE.
145+ if model_path :
146+ env_py_path = os .path .join (directory , 'env.py' )
147+ if os .path .exists (env_py_path ):
148+ with open (env_py_path , 'r' ) as f :
149+ content = f .read ()
150+ try :
151+ content = content .replace (
152+ " context.configure(\n connection=connection,\n target_metadata=target_metadata,\n process_revision_directives=process_revision_directives,\n )" ,
153+ " from sqlalchemy.engine import Connection\n def is_sqlite(conn: Connection) -> bool:\n return conn.dialect.name == \" sqlite\" \n context.configure(\n connection=connection,\n target_metadata=target_metadata,\n process_revision_directives=process_revision_directives,\n render_as_batch=is_sqlite(connection),\n )"
154+ )
155+ with open (env_py_path , 'w' ) as f :
156+ f .write (content )
157+ except ValueError :
158+ print (
159+ "Warning: If your database is SQLite, you need to manually add `render_as_batch=True` in run_migrations_online() to avoid migration errors caused by SQLite's limited support for ALTER TABLE." )
160+ else :
161+ print (
162+ "Warning: If your database is SQLite, you need to manually add `render_as_batch=True` in run_migrations_online() to avoid migration errors caused by SQLite's limited support for ALTER TABLE." )
163+
164+
199165@catch_errors
200166def init (directory : str = 'migrations' , multidb : bool = False , template : Optional [str ] = None , package : bool = False ,
201167 db_url : Optional [str ] = None , model_path : Optional [str ] = None ) -> None :
@@ -260,6 +226,7 @@ def init(directory: str = 'migrations', multidb: bool = False, template: Optiona
260226 command .init (config , directory , template = template_path , package = package )
261227
262228 _auto_configure_migrations (directory , db_url , model_path )
229+ _special_configure_for_sqlite (directory , model_path )
263230
264231
265232@catch_errors
0 commit comments