Skip to content

Commit a9b9b58

Browse files
authored
Fix and update alembic env and ini (#474)
1 parent f90b466 commit a9b9b58

File tree

3 files changed

+77
-44
lines changed

3 files changed

+77
-44
lines changed

backend/alembic.ini

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
# A generic, single database configuration.
22

33
[alembic]
4-
# path to migration scripts
4+
# path to migration scripts.
5+
# Use forward slashes (/) also on windows to provide an os agnostic path
56
script_location = alembic
67

7-
# template used to generate migration files
8-
file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(hour).2d-%%(minute).2d_%%(rev)s_%%(slug)s
8+
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
9+
# Uncomment the line below if you want the files to be prepended with date and time
10+
file_template = %%(year)d-%%(month).2d-%%(day).2d-%%(hour).2d:%%(minute).2d:%%(second).2d-%%(rev)s_%%(slug)s
911

1012
# sys.path path, will be prepended to sys.path if present.
1113
# defaults to the current working directory.
1214
prepend_sys_path = .
1315

1416
# timezone to use when rendering the date within the migration file
1517
# as well as the filename.
16-
# If specified, requires the python-dateutil library that can be
17-
# installed by adding `alembic[tz]` to the pip requirements
18-
# string value is passed to dateutil.tz.gettz()
18+
# If specified, requires the python>=3.9 or backports.zoneinfo library.
19+
# Any required deps can installed by adding `alembic[tz]` to the pip requirements
20+
# string value is passed to ZoneInfo()
1921
# leave blank for localtime
2022
# timezone =
2123

22-
# max length of characters to apply to the
23-
# "slug" field
24+
# max length of characters to apply to the "slug" field
2425
# truncate_slug_length = 40
2526

2627
# set to 'true' to run the environment during
@@ -35,16 +36,24 @@ prepend_sys_path = .
3536
# version location specification; This defaults
3637
# to alembic/versions. When using multiple version
3738
# directories, initial revisions must be specified with --version-path.
38-
# The path separator used here should be the separator specified by "version_path_separator"
39+
# The path separator used here should be the separator specified by "version_path_separator" below.
3940
# version_locations = %(here)s/bar:%(here)s/bat:alembic/versions
4041

4142
# version path separator; As mentioned above, this is the character used to split
42-
# version_locations. Valid values are:
43+
# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
44+
# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
45+
# Valid values for version_path_separator are:
4346
#
4447
# version_path_separator = :
4548
# version_path_separator = ;
4649
# version_path_separator = space
47-
version_path_separator = os # default: use os.pathsep
50+
# version_path_separator = newline
51+
version_path_separator = os # Use os.pathsep. Default configuration used for new projects.
52+
53+
# set to 'true' to search source files recursively
54+
# in each "version_locations" directory
55+
# new in Alembic version 1.10
56+
# recursive_version_locations = false
4857

4958
# the output encoding used when revision files
5059
# are written from script.py.mako
@@ -64,6 +73,12 @@ sqlalchemy.url = driver://user:pass@localhost/dbname
6473
# black.entrypoint = black
6574
# black.options = -l 79 REVISION_SCRIPT_FILENAME
6675

76+
# lint with attempts to fix using "ruff" - use the exec runner, execute a binary
77+
# hooks = ruff
78+
# ruff.type = exec
79+
# ruff.executable = %(here)s/.venv/bin/ruff
80+
# ruff.options = --fix REVISION_SCRIPT_FILENAME
81+
6782
# Logging configuration
6883
[loggers]
6984
keys = root,sqlalchemy,alembic

backend/alembic/env.py

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,44 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3-
# ruff: noqa: E402, F403, I001, RUF100
3+
# ruff: noqa: F403, F401, I001, RUF100
44
import asyncio
55
import os
66
import sys
7-
87
from logging.config import fileConfig
98

109
from alembic import context
11-
from sqlalchemy import engine_from_config, pool
12-
from sqlalchemy.ext.asyncio import AsyncEngine
10+
from sqlalchemy import pool
11+
from sqlalchemy.engine import Connection
12+
from sqlalchemy.ext.asyncio import async_engine_from_config
1313

1414
sys.path.append('../')
1515

16+
from backend.common.model import MappedBase
1617
from backend.core import path_conf
18+
from backend.database.db_mysql import SQLALCHEMY_DATABASE_URL
19+
20+
# import your new model here
21+
from backend.app.admin.model import * # noqa: F401
22+
from backend.app.generator.model import * # noqa: F401
1723

18-
if not os.path.exists(path_conf.ALEMBIC_Versions_DIR):
19-
os.makedirs(path_conf.ALEMBIC_Versions_DIR)
24+
if not os.path.exists(path_conf.ALEMBIC_VERSION_DIR):
25+
os.makedirs(path_conf.ALEMBIC_VERSION_DIR)
2026

2127
# this is the Alembic Config object, which provides
2228
# access to the values within the .ini file in use.
23-
config = context.config
29+
alembic_config = context.config
2430

2531
# Interpret the config file for Python logging.
2632
# This line sets up loggers basically.
27-
fileConfig(config.config_file_name)
33+
if alembic_config.config_file_name is not None:
34+
fileConfig(alembic_config.config_file_name)
2835

29-
# add your model's MetaData object here
36+
# model's MetaData object
3037
# for 'autogenerate' support
31-
from backend.common.model import MappedBase
32-
33-
# if add new app, do like this
34-
from backend.app.admin.model import * # noqa: F401
35-
from backend.app.generator.model import * # noqa: F401
36-
3738
target_metadata = MappedBase.metadata
3839

3940
# other values from the config, defined by the needs of env.py,
40-
from backend.database.db_mysql import SQLALCHEMY_DATABASE_URL
41-
42-
config.set_main_option('sqlalchemy.url', SQLALCHEMY_DATABASE_URL)
41+
alembic_config.set_main_option('sqlalchemy.url', SQLALCHEMY_DATABASE_URL)
4342

4443

4544
def run_migrations_offline():
@@ -54,49 +53,68 @@ def run_migrations_offline():
5453
script output.
5554
5655
"""
57-
url = config.get_main_option('sqlalchemy.url')
56+
url = alembic_config.get_main_option('sqlalchemy.url')
5857
context.configure(
5958
url=url,
6059
target_metadata=target_metadata,
6160
literal_binds=True,
6261
dialect_opts={'paramstyle': 'named'},
62+
compare_type=True,
63+
compare_server_default=True,
64+
transaction_per_migration=True,
6365
)
6466

6567
with context.begin_transaction():
6668
context.run_migrations()
6769

6870

69-
def do_run_migrations(connection):
71+
def do_run_migrations(connection: Connection) -> None:
72+
# 当迁移无变化时,不生成迁移记录
73+
def process_revision_directives(context, revision, directives):
74+
if alembic_config.cmd_opts.autogenerate:
75+
script = directives[0]
76+
if script.upgrade_ops.is_empty():
77+
directives[:] = []
78+
print('\nNo changes in model detected')
79+
7080
context.configure(
7181
connection=connection,
7282
target_metadata=target_metadata,
83+
compare_type=True,
84+
compare_server_default=True,
85+
transaction_per_migration=True,
86+
process_revision_directives=process_revision_directives,
7387
)
7488

7589
with context.begin_transaction():
7690
context.run_migrations()
7791

7892

79-
async def run_migrations_online():
80-
"""Run migrations in 'online' mode.
81-
82-
In this scenario we need to create an Engine
93+
async def run_async_migrations() -> None:
94+
"""In this scenario we need to create an Engine
8395
and associate a connection with the context.
8496
8597
"""
86-
connectable = AsyncEngine(
87-
engine_from_config(
88-
config.get_section(config.config_ini_section),
89-
prefix='sqlalchemy.',
90-
poolclass=pool.NullPool,
91-
future=True,
92-
)
98+
99+
connectable = async_engine_from_config(
100+
alembic_config.get_section(alembic_config.config_ini_section, {}),
101+
prefix='sqlalchemy.',
102+
poolclass=pool.NullPool,
93103
)
94104

95105
async with connectable.connect() as connection:
96106
await connection.run_sync(do_run_migrations)
97107

108+
await connectable.dispose()
109+
110+
111+
def run_migrations_online() -> None:
112+
"""Run migrations in 'online' mode."""
113+
114+
asyncio.run(run_async_migrations())
115+
98116

99117
if context.is_offline_mode():
100118
run_migrations_offline()
101119
else:
102-
asyncio.run(run_migrations_online())
120+
run_migrations_online()

backend/core/path_conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
BasePath = Path(__file__).resolve().parent.parent
1010

1111
# alembic 迁移文件存放路径
12-
ALEMBIC_Versions_DIR = os.path.join(BasePath, 'alembic', 'versions')
12+
ALEMBIC_VERSION_DIR = os.path.join(BasePath, 'alembic', 'versions')
1313

1414
# 日志文件路径
1515
LOG_DIR = os.path.join(BasePath, 'log')

0 commit comments

Comments
 (0)