Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render_python_code crashing when using server_default option in Column #635

Closed
ElPincheTopo opened this issue Dec 13, 2019 · 3 comments
Closed
Labels
autogenerate - rendering bug Something isn't working

Comments

@ElPincheTopo
Copy link

The function alembic.autogenerate.render_python_code doesn't work when you use server_default=func.current_timestamp()) in a column.

It used to work in alembic<=1.0.10 but it seems to be broken in any version since 1.0.11 up to 1.3.1. I'm using python 3.8, postgres 11.4 on ubuntu 18.10.

This is how to reproduce the problem:

from sqlalchemy import Table, Column, DateTime, func, MetaData, create_engine
from alembic.autogenerate import produce_migrations, render_python_code
from alembic.runtime.migration import MigrationContext

meta = MetaData()
engine = create_engine('postgresql+psycopg2://postgres:@localhost:32788/postgres')

c = Column('created_at', DateTime, server_default=func.current_timestamp())
t = Table('some_table', meta, c)

mc = MigrationContext.configure(engine.connect(), opts={'compare_type': True})
mig = produce_migrations(mc, meta)
python_code = render_python_code(mig.upgrade_ops, render_as_batch=False)

print(python_code)

This is the output on alembic <= 1.0.10:

# ### commands auto generated by Alembic - please adjust! ###
    op.create_table('some_table',
    sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True)
    )
# ### end Alembic commands ###

And in alembic >= 1.0.11 it fails on this line:

python_code = render_python_code(mig.upgrade_ops, render_as_batch=False)

This is the output:

  File ".virtualenv/lib/python3.8/site-packages/alembic/autogenerate/api.py", line 164, in render_python_code
    render._render_cmd_body(up_or_down_op, autogen_context)
  File ".virtualenv/lib/python3.8/site-packages/alembic/autogenerate/render.py", line 71, in _render_cmd_body
    lines = render_op(autogen_context, op)
  File ".virtualenv/lib/python3.8/site-packages/alembic/autogenerate/render.py", line 87, in render_op
    lines = util.to_list(renderer(autogen_context, op))
  File ".virtualenv/lib/python3.8/site-packages/alembic/autogenerate/render.py", line 172, in _add_table
    for col in [
  File ".virtualenv/lib/python3.8/site-packages/alembic/autogenerate/render.py", line 173, in <listcomp>
    _render_column(col, autogen_context) for col in table.columns
  File ".virtualenv/lib/python3.8/site-packages/alembic/autogenerate/render.py", line 601, in _render_column
    rendered = _render_server_default(
  File ".virtualenv/lib/python3.8/site-packages/alembic/autogenerate/render.py", line 650, in _render_server_default
    return _render_potential_expr(
  File ".virtualenv/lib/python3.8/site-packages/alembic/autogenerate/render.py", line 509, in _render_potential_expr
    "sql": autogen_context.migration_context.impl.render_ddl_sql_expr(
AttributeError: 'NoneType' object has no attribute 'impl'

Not sure if I'm doing something wrong or if this was accidentally broken in release 1.0.11.

@zzzeek
Copy link
Member

zzzeek commented Dec 13, 2019

regression caused by #579

@sqla-tester
Copy link
Collaborator

Mike Bayer has proposed a fix for this issue in the master branch:

Provide a context for render_python_code https://gerrit.sqlalchemy.org/1610

@zzzeek
Copy link
Member

zzzeek commented Dec 13, 2019

this will be in the next release. there is no workaround other than using the private APIs directly and passing in your migration context, as in this patch:


diff --git a/alembic/autogenerate/api.py b/alembic/autogenerate/api.py
index 709e97d..db929d0 100644
--- a/alembic/autogenerate/api.py
+++ b/alembic/autogenerate/api.py
@@ -143,6 +143,7 @@ def render_python_code(
     render_as_batch=False,
     imports=(),
     render_item=None,
+    migration_context=None,
 ):
     """Render Python code given an :class:`.UpgradeOps` or
     :class:`.DowngradeOps` object.
@@ -158,7 +159,15 @@ def render_python_code(
         "render_as_batch": render_as_batch,
     }
 
-    autogen_context = AutogenContext(None, opts=opts)
+    if migration_context is None:
+        from ..runtime.migration import MigrationContext
+        from sqlalchemy.engine.default import DefaultDialect
+
+        migration_context = MigrationContext.configure(
+            dialect=DefaultDialect()
+        )
+
+    autogen_context = AutogenContext(migration_context, opts=opts)
     autogen_context.imports = set(imports)
     return render._indent(
         render._render_cmd_body(up_or_down_op, autogen_context)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
autogenerate - rendering bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants