From: Ajaysingh-2003 Date: Wed, 8 Apr 2026 13:45:05 +0000 (-0400) Subject: Fix rendering of Column objects in dialect kwargs like postgresql_inc… X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2ddef1e4bd1b97f091038b782ee1de5fce0b1385;p=thirdparty%2Fsqlalchemy%2Falembic.git Fix rendering of Column objects in dialect kwargs like postgresql_inc… 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. Fixes: #1258 Closes: #1802 Pull-request: https://github.com/sqlalchemy/alembic/pull/1802 Pull-request-sha: 2a0441c3b21602ea6bd83aca0877f562c2c64c25 Change-Id: Idc8f1d785899ec1b2b972d6e50813afe136e47a0 --- diff --git a/alembic/autogenerate/render.py b/alembic/autogenerate/render.py index 7f32838d..4cae1cf3 100644 --- a/alembic/autogenerate/render.py +++ b/alembic/autogenerate/render.py @@ -618,7 +618,22 @@ def _render_potential_expr( is_server_default: bool = False, is_index: bool = False, ) -> str: - if isinstance(value, sql.ClauseElement): + + if isinstance(value, (list, tuple)): + rendered = [ + _render_potential_expr(item, autogen_context) for item in value + ] + if isinstance(value, tuple): + return "(%s%s)" % ( + ", ".join(rendered), + "," if len(rendered) == 1 else "", + ) + else: + return "[%s]" % ", ".join(rendered) + + elif isinstance(value, sa_schema.Column): + return repr(_ident(getattr(value, "name", None))) + elif isinstance(value, sql.ClauseElement): sql_text = autogen_context.migration_context.impl.render_ddl_sql_expr( value, is_server_default=is_server_default, is_index=is_index ) diff --git a/docs/build/unreleased/1258.rst b/docs/build/unreleased/1258.rst new file mode 100644 index 00000000..ad73a656 --- /dev/null +++ b/docs/build/unreleased/1258.rst @@ -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. diff --git a/tests/test_autogen_render.py b/tests/test_autogen_render.py index 0e7899f8..2c466497 100644 --- a/tests/test_autogen_render.py +++ b/tests/test_autogen_render.py @@ -147,6 +147,25 @@ class AutogenRenderTest(TestBase): "['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 @@ -316,6 +335,25 @@ class AutogenRenderTest(TestBase): "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()