'NoneType' object has no attribute 'autogenerate' #1089
-
Describe the bug command.revision(
Config('./alembic.ini'),
message='first_revision',
autogenerate=True,
) will fail with Expected behavior To Reproduce
# -*- coding: utf-8 -*-
"""Dataclass for database ORM."""
# built-in
from datetime import datetime
# external
from sqlmodel import Field, SQLModel, String
class SimpleModel(SQLModel, table=True):
__tablename__ = "model"
id: int = Field(primary_key=True)
name: str | None = Field(index=True)
age: str | None = Field(index=True)
from alembic import command
from alembic.config import Config
alembic_cfg = Config('./alembic.ini')
command.revision(
alembic_cfg,
message='first_revision',
autogenerate=True,
)
# -*- coding: utf-8 -*-
"""Alembic script for handling migrations."""
# built-in
from logging.config import fileConfig
# external
from alembic import context, migration
from sqlalchemy import engine_from_config, pool
from sqlmodel import SQLModel
from model import SimpleModel
# 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)
target_metadata = SQLModel.metadata
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"},
)
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.
"""
def process_revision_directives(
context: migration.MigrationContext, revision: tuple[str], directives
) -> None:
if config.cmd_opts.autogenerate:
script = directives[0]
if script.upgrade_ops.is_empty()
directives[:] = []
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata,
process_revision_directives=process_revision_directives,
)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online() Versions.
Error Stack trace```Traceback (most recent call last):
|
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 3 replies
-
commenting out context.configure(
connection=connection,
target_metadata=target_metadata,
# process_revision_directives=process_revision_directives,
) will make it work, however, it will result in an empty migration every time the code is run. |
Beta Was this translation helpful? Give feedback.
-
your process_revision_directives function is hardcoded to look for config.cmd_opts which is not present if you run command.revision() directly. you can produce a cmd_opts structure like this: from alembic.config import CommandLine
# edited for correct parse_args
namespace = CommandLine().parser.parse_args(["revision", "--autogenerate"])
alembic_cfg = Config('./alembic.ini', cmd_opts=namspace)
command.revision(
alembic_cfg,
message='first_revision',
autogenerate=True,
) |
Beta Was this translation helpful? Give feedback.
-
namespace = CommandLine().parser.parse_args("revision")
|
Beta Was this translation helpful? Give feedback.
-
Found the reason lib/python/3.10/argparse.py def parse_known_args(self, args=None, namespace=None):
if args is None:
# args default to the system args
args = _sys.argv[1:]
else:
# make sure that args are mutable
args = list(args)
### This will work namespace = CommandLine().parser.parse_args(["revision", "--autogenerate"]) # now it's a list[str] |
Beta Was this translation helpful? Give feedback.
-
New to migrations. When latest migration is not yet applied, command
Cool. When I apply changes to database, Is this expected behavior, or I don't understand how to use a tool? |
Beta Was this translation helpful? Give feedback.
Found the reason
lib/python/3.10/argparse.py
This will work