'tablename': table.name,
'prefix': _alembic_autogenerate_prefix(autogen_context),
'args': ',\n'.join(
- [_render_column(col, autogen_context) for col in table.c] +
+ [col for col in
+ [_render_column(col, autogen_context) for col in table.c]
+ if col] +
sorted([rcons for rcons in
[_render_constraint(cons, autogen_context) for cons in
table.constraints]
text += ",\n%sexisting_type=%s" % (indent,
_repr_type(sqla_prefix, existing_type, autogen_context))
if server_default is not False:
- text += ",\n%sserver_default=%s" % (indent,
- _render_server_default(
- server_default, autogen_context),)
+ rendered = _render_server_default(
+ server_default, autogen_context)
+ text += ",\n%sserver_default=%s" % (indent, rendered)
+
if type_ is not None:
text += ",\n%stype_=%s" % (indent,
_repr_type(sqla_prefix, type_, autogen_context))
text += ",\n%sexisting_nullable=%r" % (
indent, existing_nullable)
if existing_server_default:
- text += ",\n%sexisting_server_default=%s" % (
- indent,
- _render_server_default(
+ rendered = _render_server_default(
existing_server_default,
- autogen_context),
- )
+ autogen_context)
+ text += ",\n%sexisting_server_default=%s" % (
+ indent, rendered)
if schema:
text += ",\n%sschema=%r" % (indent, schema)
text += ")"
def _alembic_autogenerate_prefix(autogen_context):
return autogen_context['opts']['alembic_module_prefix'] or ''
+
+def _user_defined_render(type_, object_, autogen_context):
+ if 'opts' in autogen_context and \
+ 'render_item' in autogen_context['opts']:
+ render = autogen_context['opts']['render_item']
+ if render:
+ rendered = render(type_, object_, autogen_context)
+ if rendered is not False:
+ return rendered
+ return False
+
def _render_column(column, autogen_context):
+ rendered = _user_defined_render("column", column, autogen_context)
+ if rendered is not False:
+ return rendered
+
opts = []
if column.server_default:
- opts.append(("server_default",
- _render_server_default(
+ rendered = _render_server_default(
column.server_default, autogen_context
- )))
+ )
+ if rendered:
+ opts.append(("server_default", rendered))
+
if not column.autoincrement:
opts.append(("autoincrement", column.autoincrement))
}
def _render_server_default(default, autogen_context):
+ rendered = _user_defined_render("server_default", default, autogen_context)
+ if rendered is not False:
+ return rendered
+
if isinstance(default, sa_schema.DefaultClause):
if isinstance(default.arg, basestring):
default = default.arg
return None
def _repr_type(prefix, type_, autogen_context):
+ rendered = _user_defined_render("type", type_, autogen_context)
+ if rendered is not False:
+ return rendered
+
mod = type(type_).__module__
imports = autogen_context.get('imports', None)
if mod.startswith("sqlalchemy.dialects"):
return None
def _render_primary_key(constraint, autogen_context):
+ rendered = _user_defined_render("primary_key", constraint, autogen_context)
+ if rendered is not False:
+ return rendered
+
opts = []
if constraint.name:
opts.append(("name", repr(constraint.name)))
return fk._colspec
def _render_foreign_key(constraint, autogen_context):
+ rendered = _user_defined_render("foreign_key", constraint, autogen_context)
+ if rendered is not False:
+ return rendered
+
opts = []
if constraint.name:
opts.append(("name", repr(constraint.name)))
}
def _render_check_constraint(constraint, autogen_context):
+ rendered = _user_defined_render("check", constraint, autogen_context)
+ if rendered is not False:
+ return rendered
+
# detect the constraint being part of
# a parent type which is probably in the Table already.
# ideally SQLAlchemy would give us more of a first class
}
def _render_unique_constraint(constraint, autogen_context):
+ rendered = _user_defined_render("unique", constraint, autogen_context)
+ if rendered is not False:
+ return rendered
+
opts = []
if constraint.name:
opts.append(("name", "'%s'" % constraint.name))
include_schemas=False,
compare_type=False,
compare_server_default=False,
+ render_item=None,
upgrade_token="upgrades",
downgrade_token="downgrades",
alembic_module_prefix="op.",
.. versionchanged:: 0.4.0 the ``include_symbol`` callable must now
also accept a "schema" argument, which may be None.
+ :param render_item: Callable that can be used to override how
+ any schema item, i.e. column, constraint, type,
+ etc., is rendered for autogenerate. The callable receives a
+ string describing the type of object, the object, and
+ the autogen context. If it returns False, the
+ default rendering method will be used. If it returns None,
+ the item will not be rendered in the context of a Table
+ construct, that is, can be used to skip columns or constraints
+ within op.create_table()::
+
+ def my_render_column(type_, col, autogen_context):
+ if type_ == "column" and isinstance(col, MySpecialCol):
+ return repr(col)
+ else:
+ return False
+
+ context.configure(
+ # ...
+ render_item = my_render_column
+ )
+
+ Available values for the type string include: ``column``,
+ ``primary_key``, ``foreign_key``, ``unique``, ``check``,
+ ``type``, ``server_default``.
+
+ .. versionadded:: 0.5.0
+
:param upgrade_token: When autogenerate completes, the text of the
candidate upgrade operations will be present in this template
variable when ``script.py.mako`` is rendered. Defaults to
opts['downgrade_token'] = downgrade_token
opts['sqlalchemy_module_prefix'] = sqlalchemy_module_prefix
opts['alembic_module_prefix'] = alembic_module_prefix
+ if render_item is not None:
+ opts['render_item'] = render_item
if compare_type is not None:
opts['compare_type'] = compare_type
if compare_server_default is not None:
from sqlalchemy import MetaData, Column, Table, Integer, String, Text, \
Numeric, CHAR, ForeignKey, DATETIME, \
TypeDecorator, CheckConstraint, Unicode, Enum,\
- UniqueConstraint, Boolean, ForeignKeyConstraint
+ UniqueConstraint, Boolean, ForeignKeyConstraint,\
+ PrimaryKeyConstraint
from sqlalchemy.types import NULLTYPE, TIMESTAMP
from sqlalchemy.dialects import mysql
from sqlalchemy.engine.reflection import Inspector
'nullable=False)'
)
+ def test_render_custom(self):
+
+ def render(type_, obj, context):
+ if type_ == "foreign_key":
+ return None
+ if type_ == "column":
+ if obj.name == "y":
+ return None
+ else:
+ return "col(%s)" % obj.name
+ return "render:%s" % type_
+
+ autogen_context = {"opts": {
+ 'render_item': render,
+ 'alembic_module_prefix': 'sa.'
+ }}
+
+ t = Table('t', MetaData(),
+ Column('x', Integer),
+ Column('y', Integer),
+ PrimaryKeyConstraint('x'),
+ ForeignKeyConstraint(['x'], ['y'])
+ )
+ result = autogenerate._add_table(
+ t, autogen_context
+ )
+ eq_(
+ result, """sa.create_table('t',
+col(x),
+render:primary_key\n)"""
+ )
def test_render_modify_type(self):
eq_ignore_whitespace(