]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
- Fixed a variety of issues surrounding rendering of Python code that
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 17 Nov 2014 02:44:16 +0000 (21:44 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 17 Nov 2014 02:44:16 +0000 (21:44 -0500)
contains unicode literals.  The first is that the "quoted_name" construct
that SQLAlchemy uses to represent table and column names as well
as schema names does not ``repr()`` correctly on Py2K when the value
contains unicode characters; therefore an explicit stringification is
added to these.  Additionally, SQL expressions such as server defaults
were not being generated in a unicode-safe fashion leading to decode
errors if server defaults contained non-ascii characters.
fixes #243

alembic/autogenerate/render.py
alembic/compat.py
alembic/testing/assertions.py
alembic/testing/exclusions.py
docs/build/changelog.rst
tests/test_autogen_render.py

index 5fdfe3662c04e8d35bf1cca51bf1d68874d55ea1..d14842ec8cc945912787b31d0383cb4530bf7566 100644 (file)
@@ -28,7 +28,33 @@ class _f_name(object):
         self.name = name
 
     def __repr__(self):
-        return "%sf(%r)" % (self.prefix, self.name)
+        return "%sf(%r)" % (self.prefix, _ident(self.name))
+
+
+def _ident(name):
+    """produce a __repr__() object for a string identifier that may
+    use quoted_name() in SQLAlchemy 0.9 and greater.
+
+    The issue worked around here is that quoted_name() doesn't have
+    very good repr() behavior by itself when unicode is involved.
+
+    """
+    if name is None:
+        return name
+    elif compat.sqla_09 and isinstance(name, sql.elements.quoted_name):
+        if compat.py2k:
+            # the attempt to encode to ascii here isn't super ideal,
+            # however we are trying to cut down on an explosion of
+            # u'' literals only when py2k + SQLA 0.9, in particular
+            # makes unit tests testing code generation very difficult
+            try:
+                return name.encode('ascii')
+            except UnicodeError:
+                return compat.text_type(name)
+        else:
+            return compat.text_type(name)
+    elif isinstance(name, compat.string_types):
+        return name
 
 
 def _render_potential_expr(value, autogen_context, wrap_in_text=True):
@@ -45,7 +71,7 @@ def _render_potential_expr(value, autogen_context, wrap_in_text=True):
 
         return template % {
             "prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
-            "sql": str(
+            "sql": compat.text_type(
                 value.compile(dialect=autogen_context['dialect'],
                               **compile_kw)
             )
@@ -71,12 +97,12 @@ def _add_table(table, autogen_context):
         args = ',\n'.join(args)
 
     text = "%(prefix)screate_table(%(tablename)r,\n%(args)s" % {
-        'tablename': table.name,
+        'tablename': _ident(table.name),
         'prefix': _alembic_autogenerate_prefix(autogen_context),
         'args': args,
     }
     if table.schema:
-        text += ",\nschema=%r" % table.schema
+        text += ",\nschema=%r" % _ident(table.schema)
     for k in sorted(table.kwargs):
         text += ",\n%s=%r" % (k.replace(" ", "_"), table.kwargs[k])
     text += "\n)"
@@ -86,22 +112,23 @@ def _add_table(table, autogen_context):
 def _drop_table(table, autogen_context):
     text = "%(prefix)sdrop_table(%(tname)r" % {
         "prefix": _alembic_autogenerate_prefix(autogen_context),
-        "tname": table.name
+        "tname": _ident(table.name)
     }
     if table.schema:
-        text += ", schema=%r" % table.schema
+        text += ", schema=%r" % _ident(table.schema)
     text += ")"
     return text
 
 
 def _get_index_rendered_expressions(idx, autogen_context):
     if compat.sqla_08:
-        return [repr(getattr(exp, "name", None))
+        return [repr(_ident(getattr(exp, "name", None)))
                 if isinstance(exp, sa_schema.Column)
                 else _render_potential_expr(exp, autogen_context)
                 for exp in idx.expressions]
     else:
-        return [repr(getattr(col, "name", None)) for col in idx.columns]
+        return [
+            repr(_ident(getattr(col, "name", None))) for col in idx.columns]
 
 
 def _add_index(index, autogen_context):
@@ -110,15 +137,15 @@ def _add_index(index, autogen_context):
     :class:`~sqlalchemy.schema.Index` instance.
     """
 
-    text = "%(prefix)screate_index(%(name)r, '%(table)s', [%(columns)s], "\
+    text = "%(prefix)screate_index(%(name)r, %(table)r, [%(columns)s], "\
         "unique=%(unique)r%(schema)s%(kwargs)s)" % {
             'prefix': _alembic_autogenerate_prefix(autogen_context),
             'name': _render_gen_name(autogen_context, index.name),
-            'table': index.table.name,
+            'table': _ident(index.table.name),
             'columns': ", ".join(
                 _get_index_rendered_expressions(index, autogen_context)),
             'unique': index.unique or False,
-            'schema': (", schema='%s'" % index.table.schema)
+            'schema': (", schema=%r" % _ident(index.table.schema))
             if index.table.schema else '',
             'kwargs': (
                 ', ' +
@@ -137,11 +164,11 @@ def _drop_index(index, autogen_context):
     :class:`~sqlalchemy.schema.Index` instance.
     """
     text = "%(prefix)sdrop_index(%(name)r, "\
-        "table_name='%(table_name)s'%(schema)s)" % {
+        "table_name=%(table_name)r%(schema)s)" % {
             'prefix': _alembic_autogenerate_prefix(autogen_context),
             'name': _render_gen_name(autogen_context, index.name),
-            'table_name': index.table.name,
-            'schema': ((", schema='%s'" % index.table.schema)
+            'table_name': _ident(index.table.name),
+            'schema': ((", schema=%r" % _ident(index.table.schema))
                        if index.table.schema else '')
         }
     return text
@@ -173,23 +200,25 @@ def _uq_constraint(constraint, autogen_context, alter):
     if constraint.initially:
         opts.append(("initially", str(constraint.initially)))
     if not has_batch and alter and constraint.table.schema:
-        opts.append(("schema", str(constraint.table.schema)))
+        opts.append(("schema", _ident(constraint.table.schema)))
     if not alter and constraint.name:
         opts.append(
-            ("name", _render_gen_name(autogen_context, constraint.name)))
+            ("name",
+             _render_gen_name(autogen_context, constraint.name)))
 
     if alter:
-        args = [repr(_render_gen_name(autogen_context, constraint.name))]
+        args = [
+            repr(_render_gen_name(autogen_context, constraint.name))]
         if not has_batch:
-            args += [repr(constraint.table.name)]
-        args.append(repr([col.name for col in constraint.columns]))
+            args += [repr(_ident(constraint.table.name))]
+        args.append(repr([_ident(col.name) for col in constraint.columns]))
         args.extend(["%s=%r" % (k, v) for k, v in opts])
         return "%(prefix)screate_unique_constraint(%(args)s)" % {
             'prefix': _alembic_autogenerate_prefix(autogen_context),
             'args': ", ".join(args)
         }
     else:
-        args = [repr(col.name) for col in constraint.columns]
+        args = [repr(_ident(col.name)) for col in constraint.columns]
         args.extend(["%s=%r" % (k, v) for k, v in opts])
         return "%(prefix)sUniqueConstraint(%(args)s)" % {
             "prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
@@ -238,8 +267,8 @@ def _drop_constraint(constraint, autogen_context):
     text = template % {
         'prefix': _alembic_autogenerate_prefix(autogen_context),
         'name': _render_gen_name(autogen_context, constraint.name),
-        'table_name': constraint.table.name,
-        'schema': (", schema='%s'" % constraint.table.schema)
+        'table_name': _ident(constraint.table.name),
+        'schema': (", schema='%s'" % _ident(constraint.table.schema))
         if constraint.table.schema else '',
     }
     return text
@@ -273,9 +302,9 @@ def _drop_column(schema, tname, column, autogen_context):
 
     text = template % {
         "prefix": _alembic_autogenerate_prefix(autogen_context),
-        "tname": tname,
-        "cname": column.name,
-        "schema": schema
+        "tname": _ident(tname),
+        "cname": _ident(column.name),
+        "schema": _ident(schema)
     }
     return text
 
@@ -382,7 +411,7 @@ def _render_column(column, autogen_context):
     # TODO: for non-ascii colname, assign a "key"
     return "%(prefix)sColumn(%(name)r, %(type)s, %(kw)s)" % {
         'prefix': _sqlalchemy_autogenerate_prefix(autogen_context),
-        'name': column.name,
+        'name': _ident(column.name),
         'type': _repr_type(column.type, autogen_context),
         'kw': ", ".join(["%s=%s" % (kwname, val) for kwname, val in opts])
     }
@@ -494,7 +523,7 @@ def _render_foreign_key(constraint, autogen_context):
         "[%(refcols)s], %(args)s)" % {
             "prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
             "cols": ", ".join(
-                "'%s'" % f.parent.key for f in constraint.elements),
+                "%r" % f.parent.key for f in constraint.elements),
             "refcols": ", ".join(repr(_fk_colspec(f, apply_metadata_schema))
                                  for f in constraint.elements),
             "args": ", ".join(
@@ -522,7 +551,8 @@ def _render_check_constraint(constraint, autogen_context):
         opts.append(
             (
                 "name",
-                repr(_render_gen_name(autogen_context, constraint.name))
+                repr(
+                    _render_gen_name(autogen_context, constraint.name))
             )
         )
     return "%(prefix)sCheckConstraint(%(sqltext)s%(opts)s)" % {
index 8c6a038ca9793797bea39f49ad639ae70bc14343..5cb1fc7b8148b2f33e6fc6a09aeb0f22f8762256 100644 (file)
@@ -30,6 +30,9 @@ if py3k:
     def u(s):
         return s
 
+    def ue(s):
+        return s
+
 else:
     import __builtin__ as compat_builtins
     string_types = basestring,
@@ -40,6 +43,9 @@ else:
     def u(s):
         return unicode(s, "utf-8")
 
+    def ue(s):
+        return unicode(s, "unicode_escape")
+
 if py3k:
     from configparser import ConfigParser as SafeConfigParser
     import configparser
@@ -96,6 +102,31 @@ def with_metaclass(meta, base=object):
     return meta("%sBase" % meta.__name__, (base,), {})
 ################################################
 
+if py3k:
+    def reraise(tp, value, tb=None, cause=None):
+        if cause is not None:
+            value.__cause__ = cause
+        if value.__traceback__ is not tb:
+            raise value.with_traceback(tb)
+        raise value
+
+    def raise_from_cause(exception, exc_info=None):
+        if exc_info is None:
+            exc_info = sys.exc_info()
+        exc_type, exc_value, exc_tb = exc_info
+        reraise(type(exception), exception, tb=exc_tb, cause=exc_value)
+else:
+    exec("def reraise(tp, value, tb=None, cause=None):\n"
+         "    raise tp, value, tb\n")
+
+    def raise_from_cause(exception, exc_info=None):
+        # not as nice as that of Py3K, but at least preserv
+        # the code line where the issue occurred
+        if exc_info is None:
+            exc_info = sys.exc_info()
+        exc_type, exc_value, exc_tb = exc_info
+        reraise(type(exception), exception, tb=exc_tb)
+
 
 # produce a wrapper that allows encoded text to stream
 # into a given buffer, but doesn't close it.
index d31057ae3c2fb3bc7c7a6a4a2f1307edf47114a2..f5e992e717e48a84d6509eee85e2c5a29a013584 100644 (file)
@@ -1,7 +1,7 @@
 import re
 from alembic import util
 from sqlalchemy.engine import default
-from alembic.compat import text_type
+from alembic.compat import text_type, py3k
 
 if not util.sqla_094:
     def eq_(a, b, msg=None):
@@ -45,6 +45,14 @@ def eq_ignore_whitespace(a, b, msg=None):
     a = re.sub(r' {2,}', " ", a)
     b = re.sub(r'^\s+?|\n', "", b)
     b = re.sub(r' {2,}', " ", b)
+
+    # convert for unicode string rendering,
+    # using special escape character "!U"
+    if py3k:
+        b = re.sub(r'!U', '', b)
+    else:
+        b = re.sub(r'!U', 'u', b)
+
     assert a == b, msg or "%r != %r" % (a, b)
 
 
index a64fe352847a2c1bcc0e32157734a1ad02e59ae5..88df9fc3f50cbebf1482be6d4caaaa47f50e0572 100644 (file)
@@ -137,7 +137,7 @@ class compound(object):
                     name, fail._as_string(config), str(ex))))
                 break
         else:
-            raise ex
+            compat.raise_from_cause(ex)
 
     def _expect_success(self, config, name='block'):
         if not self.fails:
index e790f92ef84f3c23183cfc076828931307a32c91..312ca7ee48b56a601885360aea59c9375fdc71b8 100644 (file)
@@ -5,6 +5,19 @@ Changelog
 .. changelog::
     :version: 0.7.0
 
+    .. change::
+      :tags: bug, autogenerate
+      :tickets: 243
+
+      Fixed a variety of issues surrounding rendering of Python code that
+      contains unicode literals.  The first is that the "quoted_name" construct
+      that SQLAlchemy uses to represent table and column names as well
+      as schema names does not ``repr()`` correctly on Py2K when the value
+      contains unicode characters; therefore an explicit stringification is
+      added to these.  Additionally, SQL expressions such as server defaults
+      were not being generated in a unicode-safe fashion leading to decode
+      errors if server defaults contained non-ascii characters.
+
     .. change::
       :tags: bug, operations
       :tickets: 174
index 648b3f7afcf9219e81f90b396d0f93c9b17904c8..ddd108eaf55750974671760578e2acae1e7f1ae2 100644 (file)
@@ -95,14 +95,14 @@ class AutogenRenderTest(TestBase):
                 autogenerate.render._add_index(idx, autogen_context),
                 """op.create_index('foo_idx', 't', \
 ['x', 'y'], unique=False, """
-                """postgresql_where=sa.text("t.y = 'something'"))"""
+                """postgresql_where=sa.text(!U"t.y = 'something'"))"""
             )
         else:
             eq_ignore_whitespace(
                 autogenerate.render._add_index(idx, autogen_context),
                 """op.create_index('foo_idx', 't', ['x', 'y'], \
 unique=False, """
-                """postgresql_where=sa.text('t.y = %(y_1)s'))"""
+                """postgresql_where=sa.text(!U't.y = %(y_1)s'))"""
             )
 
     @config.requirements.fail_before_sqla_080
@@ -117,7 +117,7 @@ unique=False, """
         eq_ignore_whitespace(
             autogenerate.render._add_index(idx, self.autogen_context),
             "op.create_index('test_lower_code_idx', 'test', "
-            "[sa.text('lower(test.code)')], unique=False)"
+            "[sa.text(!U'lower(test.code)')], unique=False)"
         )
 
     @config.requirements.fail_before_sqla_080
@@ -132,7 +132,7 @@ unique=False, """
         eq_ignore_whitespace(
             autogenerate.render._add_index(idx, self.autogen_context),
             "op.create_index('test_lower_code_idx', 'test', "
-            "[sa.text('CAST(test.code AS CHAR)')], unique=False)"
+            "[sa.text(!U'CAST(test.code AS CHAR)')], unique=False)"
         )
 
     @config.requirements.fail_before_sqla_080
@@ -147,7 +147,7 @@ unique=False, """
         eq_ignore_whitespace(
             autogenerate.render._add_index(idx, self.autogen_context),
             "op.create_index('test_desc_code_idx', 'test', "
-            "[sa.text('test.code DESC')], unique=False)"
+            "[sa.text(!U'test.code DESC')], unique=False)"
         )
 
     def test_drop_index(self):
@@ -300,6 +300,32 @@ unique=False, """
             ")"
         )
 
+    def test_render_table_w_unicode_name(self):
+        m = MetaData()
+        t = Table(compat.ue('\u0411\u0435\u0437'), m,
+                  Column('id', Integer, primary_key=True),
+                  )
+        eq_ignore_whitespace(
+            autogenerate.render._add_table(t, self.autogen_context),
+            "op.create_table(%r,"
+            "sa.Column('id', sa.Integer(), nullable=False),"
+            "sa.PrimaryKeyConstraint('id'))" % compat.ue('\u0411\u0435\u0437')
+        )
+
+    def test_render_table_w_unicode_schema(self):
+        m = MetaData()
+        t = Table('test', m,
+                  Column('id', Integer, primary_key=True),
+                  schema=compat.ue('\u0411\u0435\u0437')
+                  )
+        eq_ignore_whitespace(
+            autogenerate.render._add_table(t, self.autogen_context),
+            "op.create_table('test',"
+            "sa.Column('id', sa.Integer(), nullable=False),"
+            "sa.PrimaryKeyConstraint('id'),"
+            "schema=%r)" % compat.ue('\u0411\u0435\u0437')
+        )
+
     @patch("alembic.autogenerate.render.MAX_PYTHON_ARGS", 3)
     def test_render_table_max_cols(self):
         m = MetaData()
@@ -359,7 +385,8 @@ unique=False, """
         eq_ignore_whitespace(
             re.sub(
                 r"u'", "'",
-                autogenerate.render._add_table(t, self.autogen_context)),
+                autogenerate.render._add_table(t, self.autogen_context)
+            ),
             "op.create_table('test',"
             "sa.Column('id', sa.Integer(), nullable=False),"
             "sa.Column('q', sa.Integer(), nullable=True),"
@@ -404,14 +431,14 @@ unique=False, """
         )
 
     def test_render_drop_table(self):
-        eq_(
+        eq_ignore_whitespace(
             autogenerate.render._drop_table(Table("sometable", MetaData()),
                                             self.autogen_context),
             "op.drop_table('sometable')"
         )
 
     def test_render_drop_table_w_schema(self):
-        eq_(
+        eq_ignore_whitespace(
             autogenerate.render._drop_table(
                 Table("sometable", MetaData(), schema='foo'),
                 self.autogen_context),
@@ -435,7 +462,8 @@ unique=False, """
 
         eq_ignore_whitespace(
             autogenerate.render._add_table(t1, self.autogen_context),
-            "op.create_table('t1',sa.Column('x', sa.Integer(), nullable=True))"
+            "op.create_table('t1',"
+            "sa.Column('x', sa.Integer(), nullable=True))"
         )
 
         eq_ignore_whitespace(
@@ -446,7 +474,7 @@ unique=False, """
         )
 
     def test_render_add_column(self):
-        eq_(
+        eq_ignore_whitespace(
             autogenerate.render._add_column(
                 None, "foo", Column("x", Integer, server_default="5"),
                 self.autogen_context),
@@ -455,7 +483,7 @@ unique=False, """
         )
 
     def test_render_add_column_w_schema(self):
-        eq_(
+        eq_ignore_whitespace(
             autogenerate.render._add_column(
                 "foo", "bar", Column("x", Integer, server_default="5"),
                 self.autogen_context),
@@ -464,7 +492,7 @@ unique=False, """
         )
 
     def test_render_drop_column(self):
-        eq_(
+        eq_ignore_whitespace(
             autogenerate.render._drop_column(
                 None, "foo", Column("x", Integer, server_default="5"),
                 self.autogen_context),
@@ -473,7 +501,7 @@ unique=False, """
         )
 
     def test_render_drop_column_w_schema(self):
-        eq_(
+        eq_ignore_whitespace(
             autogenerate.render._drop_column(
                 "foo", "bar", Column("x", Integer, server_default="5"),
                 self.autogen_context),
@@ -489,6 +517,24 @@ unique=False, """
             '"nextval(\'group_to_perm_group_to_perm_id_seq\'::regclass)"'
         )
 
+    def test_render_unicode_server_default(self):
+        default = compat.ue(
+            '\u0411\u0435\u0437 '
+            '\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f'
+        )
+
+        c = Column(
+            'x', Unicode,
+            server_default=text(default)
+        )
+
+        eq_ignore_whitespace(
+            autogenerate.render._render_server_default(
+                c.server_default, self.autogen_context
+            ),
+            "sa.text(%r)" % default
+        )
+
     def test_render_col_with_server_default(self):
         c = Column('updated_at', TIMESTAMP(),
                    server_default='TIMEZONE("utc", CURRENT_TIMESTAMP)',
@@ -496,7 +542,7 @@ unique=False, """
         result = autogenerate.render._render_column(
             c, self.autogen_context
         )
-        eq_(
+        eq_ignore_whitespace(
             result,
             'sa.Column(\'updated_at\', sa.TIMESTAMP(), '
             'server_default=\'TIMEZONE("utc", CURRENT_TIMESTAMP)\', '
@@ -509,7 +555,7 @@ unique=False, """
         result = autogenerate.render._render_column(
             c, self.autogen_context
         )
-        eq_(
+        eq_ignore_whitespace(
             result,
             'sa.Column(\'some_key\', sa.Integer(), '
             'autoincrement=False, '
@@ -542,10 +588,11 @@ unique=False, """
         result = autogenerate.render._add_table(
             t, autogen_context
         )
-        eq_(
-            result, """sa.create_table('t',
-col(x),
-render:primary_key\n)"""
+        eq_ignore_whitespace(
+            result,
+            "sa.create_table('t',"
+            "col(x),"
+            "render:primary_key)"
         )
 
     def test_render_modify_type(self):
@@ -601,6 +648,9 @@ render:primary_key\n)"""
         if not util.sqla_08:
             t1.append_constraint(fk)
 
+        # SQLA 0.9 generates a u'' here for remote cols while 0.8 does not,
+        # so just whack out "'u" here from the generated
+
         eq_ignore_whitespace(
             re.sub(
                 r"u'", "'",
@@ -628,7 +678,8 @@ render:primary_key\n)"""
             re.sub(
                 r"u'", "'",
                 autogenerate.render._render_constraint(
-                    fk, self.autogen_context)),
+                    fk, self.autogen_context),
+            ),
             "sa.ForeignKeyConstraint(['c'], ['t2.c_rem'], deferrable=True)"
         )
 
@@ -639,7 +690,8 @@ render:primary_key\n)"""
             re.sub(
                 r"u'", "'",
                 autogenerate.render._render_constraint(
-                    fk, self.autogen_context)),
+                    fk, self.autogen_context)
+            ),
             "sa.ForeignKeyConstraint(['c'], ['t2.c_rem'], initially='XYZ')"
         )
 
@@ -673,7 +725,8 @@ render:primary_key\n)"""
             re.sub(
                 r"u'", "'",
                 autogenerate.render._render_constraint(
-                    fk, self.autogen_context)),
+                    fk, self.autogen_context)
+            ),
             "sa.ForeignKeyConstraint(['c'], ['foo.t2.c_rem'], "
             "onupdate='CASCADE')"
         )
@@ -684,7 +737,7 @@ render:primary_key\n)"""
                 CheckConstraint("im a constraint", name='cc1'),
                 self.autogen_context
             ),
-            "sa.CheckConstraint('im a constraint', name='cc1')"
+            "sa.CheckConstraint(!U'im a constraint', name='cc1')"
         )
 
     def test_render_check_constraint_sqlexpr(self):
@@ -696,7 +749,7 @@ render:primary_key\n)"""
                 CheckConstraint(and_(c > five, c < ten)),
                 self.autogen_context
             ),
-            "sa.CheckConstraint('c > 5 AND c < 10')"
+            "sa.CheckConstraint(!U'c > 5 AND c < 10')"
         )
 
     @config.requirements.fail_before_sqla_080
@@ -707,7 +760,7 @@ render:primary_key\n)"""
                 CheckConstraint(and_(c > 5, c < 10)),
                 self.autogen_context
             ),
-            "sa.CheckConstraint('c > 5 AND c < 10')"
+            "sa.CheckConstraint(!U'c > 5 AND c < 10')"
         )
 
     def test_render_unique_constraint_opts(self):
@@ -721,6 +774,21 @@ render:primary_key\n)"""
             "sa.UniqueConstraint('c', deferrable='XYZ', name='uq_1')"
         )
 
+    def test_add_unique_constraint_unicode_schema(self):
+        m = MetaData()
+        t = Table(
+            't', m, Column('c', Integer),
+            schema=compat.ue('\u0411\u0435\u0437')
+        )
+        eq_ignore_whitespace(
+            autogenerate.render._add_unique_constraint(
+                UniqueConstraint(t.c.c),
+                self.autogen_context
+            ),
+            "op.create_unique_constraint(None, 't', ['c'], "
+            "schema=%r)" % compat.ue('\u0411\u0435\u0437')
+        )
+
     def test_render_modify_nullable_w_default(self):
         eq_ignore_whitespace(
             autogenerate.render._modify_col(
@@ -839,10 +907,10 @@ render:primary_key\n)"""
         result = autogenerate.render._render_column(
             c, self.autogen_context
         )
-        eq_(
+        eq_ignore_whitespace(
             result,
             'sa.Column(\'updated_at\', sa.TIMESTAMP(), '
-            'server_default=sa.text(\'now()\'), '
+            'server_default=sa.text(!U\'now()\'), '
             'nullable=False)'
         )
 
@@ -861,10 +929,10 @@ render:primary_key\n)"""
         result = autogenerate.render._render_column(
             c, autogen_context,
         )
-        eq_(
+        eq_ignore_whitespace(
             result,
             'sa.Column(\'updated_at\', sa.Boolean(), '
-            'server_default=sa.text(\'false\'), '
+            'server_default=sa.text(!U\'false\'), '
             'nullable=False)'
         )
 
@@ -886,10 +954,10 @@ render:primary_key\n)"""
         result = autogenerate.render._render_column(
             c, autogen_context
         )
-        eq_(
+        eq_ignore_whitespace(
             result,
             'sa.Column(\'updated_at\', sa.Boolean(), '
-            'server_default=sa.text(\'0\'), '
+            'server_default=sa.text(!U\'0\'), '
             'nullable=False)'
         )
 
@@ -901,10 +969,10 @@ render:primary_key\n)"""
         result = autogenerate.render._render_column(
             c, self.autogen_context
         )
-        eq_(
+        eq_ignore_whitespace(
             result,
             'sa.Column(\'updated_at\', sa.TIMESTAMP(), '
-            'server_default=sa.text(\'now()\'), '
+            'server_default=sa.text(!U\'now()\'), '
             'nullable=False)'
         )
 
@@ -931,11 +999,10 @@ render:primary_key\n)"""
                 nullable=True),
             "op.alter_column('sometable', 'somecolumn', "
             "existing_type=sa.Integer(), nullable=True, "
-            "existing_server_default=sa.text('5'))"
+            "existing_server_default=sa.text(!U'5'))"
         )
 
 
-
 class RenderNamingConventionTest(TestBase):
     __requires__ = ('sqlalchemy_094',)
 
@@ -1059,7 +1126,7 @@ class RenderNamingConventionTest(TestBase):
         eq_ignore_whitespace(
             autogenerate.render._add_table(t, self.autogen_context),
             "op.create_table('t',sa.Column('c', sa.Integer(), nullable=True),"
-            "sa.CheckConstraint('c > 5', name=op.f('ck_ct_t')))"
+            "sa.CheckConstraint(!U'c > 5', name=op.f('ck_ct_t')))"
         )
 
     def test_inline_fk(self):
@@ -1092,6 +1159,6 @@ class RenderNamingConventionTest(TestBase):
                 ck,
                 self.autogen_context
             ),
-            "sa.CheckConstraint('im a constraint', name=op.f('ck_t_cc1'))"
+            "sa.CheckConstraint(!U'im a constraint', name=op.f('ck_t_cc1'))"
         )