Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion alembic/autogenerate/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,28 @@ def _drop_table(autogen_context: AutogenContext, op: ops.DropTableOp) -> str:
def _render_dialect_kwargs_items(
autogen_context: AutogenContext, dialect_kwargs: _DialectArgView
) -> list[str]:
def _render_kwarg_value(val: Any) -> str:
if isinstance(val, (list, tuple)):
rendered = [
(
repr(_ident(getattr(item, "name", None)))
if isinstance(item, sa_schema.Column)
else _render_potential_expr(item, autogen_context)
)
for item in val
]
if isinstance(val, tuple):
return "(%s%s)" % (
", ".join(rendered),
"," if len(rendered) == 1 else "",
)
else:
return "[%s]" % ", ".join(rendered)
else:
return _render_potential_expr(val, autogen_context)

return [
f"{key}={_render_potential_expr(val, autogen_context)}"
f"{key}={_render_kwarg_value(val)}"
for key, val in dialect_kwargs.items()
]

Expand Down
10 changes: 10 additions & 0 deletions docs/build/unreleased/1258.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. change::
:tags: bug, autogenerate
:tickets: 1258

Fixed rendering of dialect keyword arguments containing
:class:`~sqlalchemy.schema.Column` objects within sequences, such as
``postgresql_include``. These were previously rendered using ``repr()``,
producing invalid Python in the generated migration scripts. Column
objects within list or tuple values are now correctly rendered as their
string column names. Pull request courtesy Ajay Singh.
38 changes: 38 additions & 0 deletions tests/test_autogen_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,25 @@ def test_render_add_index_custom_kwarg(self):
"['active', 'code'], unique=False, somedialect_foobar='option')",
)

@testing.emits_warning("Can't validate argument ")
def test_render_add_index_dialect_kwarg_with_columns(self):
"""test that Column objects in dialect kwargs like
postgresql_include are rendered as column name strings,
not as raw Column repr.
"""
t = self.table()
idx = Index(
"test_active_code_idx",
t.c.active,
somedialect_include=[t.c.code],
)
op_obj = ops.CreateIndexOp.from_index(idx)
eq_ignore_whitespace(
autogenerate.render_op_text(self.autogen_context, op_obj),
"op.create_index('test_active_code_idx', 'test', "
"['active'], unique=False, somedialect_include=['code'])",
)

def test_render_add_index_batch(self):
"""
autogenerate.render._add_index
Expand Down Expand Up @@ -316,6 +335,25 @@ def test_render_drop_index_custom_kwarg(self):
"somedialect_foobar='option')",
)

@testing.emits_warning("Can't validate argument ")
def test_render_drop_index_dialect_kwarg_with_columns(self):
"""test that Column objects in dialect kwargs like
postgresql_include are rendered as column name strings
in drop_index, not as raw Column repr.
"""
t = self.table()
idx = Index(
"test_active_code_idx",
t.c.active,
somedialect_include=(t.c.code,),
)
op_obj = ops.DropIndexOp.from_index(idx)
eq_ignore_whitespace(
autogenerate.render_op_text(self.autogen_context, op_obj),
"op.drop_index('test_active_code_idx', table_name='test', "
"somedialect_include=('code',))",
)

def test_add_fk_constraint__dialect_kwargs(self):
t1 = self.table()
t2 = self.table()
Expand Down
Loading