Skip to content

Commit 3db374f

Browse files
lachaibzzzeek
authored andcommitted
Render if_not_exists option for CreateTableOp, CreateIndexOp, DropTableOp and DropIndexOp
Render ``if_exists`` and ``if_not_exists`` parameters in :class:`.CreateTableOp`, :class:`.CreateIndexOp`, :class:`.DropTableOp` and :class:`.DropIndexOp` in an autogenerate context. While Alembic does not set these parameters during an autogenerate run, they can be enabled using a custom :class:`.Rewriter` in the ``env.py`` file, where they will now be part of the rendered Python code in revision files. Pull request courtesy of Louis-Amaury Chaib (@lachaib). Closes: #1446 Pull-request: #1446 Pull-request-sha: 90c9735 Change-Id: I6b0a5ffaf7e2d1a0a1e1f1e80ed0ee168ae2bd09
1 parent 8fae3e1 commit 3db374f

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

alembic/autogenerate/render.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,9 @@ def _add_table(autogen_context: AutogenContext, op: ops.CreateTableOp) -> str:
279279
prefixes = ", ".join("'%s'" % p for p in table._prefixes)
280280
text += ",\nprefixes=[%s]" % prefixes
281281

282+
if op.if_not_exists is not None:
283+
text += ",\nif_not_exists=%r" % bool(op.if_not_exists)
284+
282285
text += "\n)"
283286
return text
284287

@@ -291,6 +294,10 @@ def _drop_table(autogen_context: AutogenContext, op: ops.DropTableOp) -> str:
291294
}
292295
if op.schema:
293296
text += ", schema=%r" % _ident(op.schema)
297+
298+
if op.if_exists is not None:
299+
text += ", if_exists=%r" % bool(op.if_exists)
300+
294301
text += ")"
295302
return text
296303

@@ -324,6 +331,8 @@ def _add_index(autogen_context: AutogenContext, op: ops.CreateIndexOp) -> str:
324331
assert index.table is not None
325332

326333
opts = _render_dialect_kwargs_items(autogen_context, index)
334+
if op.if_not_exists is not None:
335+
opts.append("if_not_exists=%r" % bool(op.if_not_exists))
327336
text = tmpl % {
328337
"prefix": _alembic_autogenerate_prefix(autogen_context),
329338
"name": _render_gen_name(autogen_context, index.name),
@@ -356,6 +365,8 @@ def _drop_index(autogen_context: AutogenContext, op: ops.DropIndexOp) -> str:
356365
"table_name=%(table_name)r%(schema)s%(kwargs)s)"
357366
)
358367
opts = _render_dialect_kwargs_items(autogen_context, index)
368+
if op.if_exists is not None:
369+
opts.append("if_exists=%r" % bool(op.if_exists))
359370
text = tmpl % {
360371
"prefix": _alembic_autogenerate_prefix(autogen_context),
361372
"name": _render_gen_name(autogen_context, op.index_name),

docs/build/unreleased/1446.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. change::
2+
:tags: usecase, autogenerate
3+
4+
Render ``if_exists`` and ``if_not_exists`` parameters in
5+
:class:`.CreateTableOp`, :class:`.CreateIndexOp`, :class:`.DropTableOp` and
6+
:class:`.DropIndexOp` in an autogenerate context. While Alembic does not
7+
set these parameters during an autogenerate run, they can be enabled using
8+
a custom :class:`.Rewriter` in the ``env.py`` file, where they will now be
9+
part of the rendered Python code in revision files. Pull request courtesy
10+
of Louis-Amaury Chaib (@lachaib).

tests/test_autogen_render.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,20 @@ def test_render_add_index(self):
9393
"['active', 'code'], unique=False)",
9494
)
9595

96+
def test_render_add_index_if_not_exists(self):
97+
"""
98+
autogenerate.render._add_index
99+
"""
100+
t = self.table()
101+
idx = Index("test_active_code_idx", t.c.active, t.c.code)
102+
op_obj = ops.CreateIndexOp.from_index(idx)
103+
op_obj.if_not_exists = True
104+
eq_ignore_whitespace(
105+
autogenerate.render_op_text(self.autogen_context, op_obj),
106+
"op.create_index('test_active_code_idx', 'test', "
107+
"['active', 'code'], unique=False, if_not_exists=True)",
108+
)
109+
96110
@testing.emits_warning("Can't validate argument ")
97111
def test_render_add_index_custom_kwarg(self):
98112
t = self.table()
@@ -212,6 +226,20 @@ def test_drop_index(self):
212226
"op.drop_index('test_active_code_idx', table_name='test')",
213227
)
214228

229+
def test_drop_index_if_exists(self):
230+
"""
231+
autogenerate.render._drop_index
232+
"""
233+
t = self.table()
234+
idx = Index("test_active_code_idx", t.c.active, t.c.code)
235+
op_obj = ops.DropIndexOp.from_index(idx)
236+
op_obj.if_exists = True
237+
eq_ignore_whitespace(
238+
autogenerate.render_op_text(self.autogen_context, op_obj),
239+
"op.drop_index('test_active_code_idx', table_name='test', "
240+
"if_exists=True)",
241+
)
242+
215243
def test_drop_index_text(self):
216244
"""
217245
autogenerate.render._drop_index
@@ -989,6 +1017,19 @@ def test_render_addtl_args(self):
9891017
"mysql_engine='InnoDB',sqlite_autoincrement=True)",
9901018
)
9911019

1020+
def test_render_if_not_exists(self):
1021+
t = self.table()
1022+
op_obj = ops.CreateTableOp.from_table(t)
1023+
op_obj.if_not_exists = True
1024+
eq_ignore_whitespace(
1025+
autogenerate.render_op_text(self.autogen_context, op_obj),
1026+
"op.create_table('test',"
1027+
"sa.Column('id', sa.Integer(), nullable=False),"
1028+
"sa.Column('active', sa.Boolean(), nullable=True),"
1029+
"sa.Column('code', sa.String(length=255), nullable=True),"
1030+
"sa.PrimaryKeyConstraint('id'),if_not_exists=True)",
1031+
)
1032+
9921033
def test_render_drop_table(self):
9931034
op_obj = ops.DropTableOp.from_table(Table("sometable", MetaData()))
9941035
eq_ignore_whitespace(
@@ -1005,6 +1046,15 @@ def test_render_drop_table_w_schema(self):
10051046
"op.drop_table('sometable', schema='foo')",
10061047
)
10071048

1049+
def test_render_drop_table_if_exists(self):
1050+
t = self.table()
1051+
op_obj = ops.DropTableOp.from_table(t)
1052+
op_obj.if_exists = True
1053+
eq_ignore_whitespace(
1054+
autogenerate.render_op_text(self.autogen_context, op_obj),
1055+
"op.drop_table('test', if_exists=True)",
1056+
)
1057+
10081058
def test_render_table_no_implicit_check(self):
10091059
m = MetaData()
10101060
t = Table("test", m, Column("x", Boolean()))

0 commit comments

Comments
 (0)