From 532767e552c66cdccb8c43266f6227c83e6cdb77 Mon Sep 17 00:00:00 2001 From: kolo Date: Fri, 27 Feb 2026 16:54:54 +0300 Subject: [PATCH] update --- alembic.ini | 2 +- alembic/env.py | 74 ++++++++-------------- alembic/versions/f012f3ef4b65_initial.py | 36 +++++++++++ src/dutylog/infrastructure/utils/config.py | 2 +- 4 files changed, 66 insertions(+), 48 deletions(-) create mode 100644 alembic/versions/f012f3ef4b65_initial.py diff --git a/alembic.ini b/alembic.ini index 807ded2..f0da7e5 100644 --- a/alembic.ini +++ b/alembic.ini @@ -86,7 +86,7 @@ path_separator = os # database URL. This is consumed by the user-maintained env.py script only. # other means of configuring database URLs may be customized within the env.py # file. -sqlalchemy.url = driver://user:pass@localhost/dbname +sqlalchemy.url = [post_write_hooks] diff --git a/alembic/env.py b/alembic/env.py index 36112a3..f674492 100644 --- a/alembic/env.py +++ b/alembic/env.py @@ -1,78 +1,60 @@ +import asyncio from logging.config import fileConfig -from sqlalchemy import engine_from_config from sqlalchemy import pool from alembic import context +from sqlalchemy.engine import Connection +from sqlalchemy.ext.asyncio import async_engine_from_config + +from src.dutylog.infrastructure.database.models.base import Base +from src.dutylog.infrastructure.database.models.user import User as User +from src.dutylog.infrastructure.utils.config import load_config -# this is the Alembic Config object, which provides -# access to the values within the .ini file in use. config = context.config -# Interpret the config file for Python logging. -# This line sets up loggers basically. if config.config_file_name is not None: fileConfig(config.config_file_name) -# add your model's MetaData object here -# for 'autogenerate' support -# from myapp import mymodel -# target_metadata = mymodel.Base.metadata -target_metadata = None +app_config = load_config() +config.set_main_option("sqlalchemy.url", app_config.database.url) + +target_metadata = Base.metadata # other values from the config, defined by the needs of env.py, # can be acquired: # my_important_option = config.get_main_option("my_important_option") # ... etc. - -def run_migrations_offline() -> None: - """Run migrations in 'offline' mode. - - This configures the context with just a URL - and not an Engine, though an Engine is acceptable - here as well. By skipping the Engine creation - we don't even need a DBAPI to be available. - - Calls to context.execute() here emit the given string to the - script output. - - """ - url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, - target_metadata=target_metadata, - literal_binds=True, - dialect_opts={"paramstyle": "named"}, - ) - +def do_run_migrations(connection: Connection): + context.configure(connection=connection, target_metadata=target_metadata) with context.begin_transaction(): context.run_migrations() -def run_migrations_online() -> None: - """Run migrations in 'online' mode. - - In this scenario we need to create an Engine - and associate a connection with the context. - - """ - connectable = engine_from_config( +async def run_async_migrations(): + connectable = async_engine_from_config( config.get_section(config.config_ini_section, {}), prefix="sqlalchemy.", poolclass=pool.NullPool, ) + async with connectable.connect() as connection: + await connection.run_sync(do_run_migrations) + await connectable.dispose() - with connectable.connect() as connection: - context.configure( - connection=connection, target_metadata=target_metadata - ) - with context.begin_transaction(): - context.run_migrations() +def run_migrations_online(): + asyncio.run(run_async_migrations()) + + +def run_migrations_offline(): + url = config.get_main_option("sqlalchemy.url") + context.configure(url=url, target_metadata=target_metadata, literal_binds=True) + with context.begin_transaction(): + context.run_migrations() if context.is_offline_mode(): run_migrations_offline() else: - run_migrations_online() + run_migrations_online() \ No newline at end of file diff --git a/alembic/versions/f012f3ef4b65_initial.py b/alembic/versions/f012f3ef4b65_initial.py new file mode 100644 index 0000000..f4e7fea --- /dev/null +++ b/alembic/versions/f012f3ef4b65_initial.py @@ -0,0 +1,36 @@ +"""initial + +Revision ID: f012f3ef4b65 +Revises: +Create Date: 2026-02-27 16:53:39.926344 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'f012f3ef4b65' +down_revision: Union[str, Sequence[str], None] = None +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('users', + sa.Column('id', sa.BigInteger(), nullable=False), + sa.Column('username', sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('users') + # ### end Alembic commands ### diff --git a/src/dutylog/infrastructure/utils/config.py b/src/dutylog/infrastructure/utils/config.py index 9bbae0d..8422098 100644 --- a/src/dutylog/infrastructure/utils/config.py +++ b/src/dutylog/infrastructure/utils/config.py @@ -21,7 +21,7 @@ class DatabaseConfig: @property def url(self) -> str: return f"postgresql+asyncpg://{self.user}:{self.password}@{self.host}:{self.port}/{self.database}" - + @dataclass class Config: