]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- wrestle with conv() and tests some more
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 15 Jul 2014 02:44:33 +0000 (22:44 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 15 Jul 2014 02:44:33 +0000 (22:44 -0400)
lib/sqlalchemy/sql/elements.py
lib/sqlalchemy/sql/naming.py
test/sql/test_metadata.py

index 1447787cef44426dd144b3d664cf20f6f97e4bc0..4f58f6141ff2e75ce3989244b21f42fda9eadce7 100644 (file)
@@ -3202,6 +3202,52 @@ class _truncated_label(quoted_name):
         return self
 
 
+class conv(_truncated_label):
+    """Mark a string indicating that a name has already been converted
+    by a naming convention.
+
+    This is a string subclass that indicates a name that should not be
+    subject to any further naming conventions.
+
+    E.g. when we create a :class:`.Constraint` using a naming convention
+    as follows::
+
+        m = MetaData(naming_convention={
+            "ck": "ck_%(table_name)s_%(constraint_name)s"
+        })
+        t = Table('t', m, Column('x', Integer),
+                        CheckConstraint('x > 5', name='x5'))
+
+    The name of the above constraint will be rendered as ``"ck_t_x5"``.
+    That is, the existing name ``x5`` is used in the naming convention as the
+    ``constraint_name`` token.
+
+    In some situations, such as in migration scripts, we may be rendering
+    the above :class:`.CheckConstraint` with a name that's already been
+    converted.  In order to make sure the name isn't double-modified, the
+    new name is applied using the :func:`.schema.conv` marker.  We can
+    use this explicitly as follows::
+
+
+        m = MetaData(naming_convention={
+            "ck": "ck_%(table_name)s_%(constraint_name)s"
+        })
+        t = Table('t', m, Column('x', Integer),
+                        CheckConstraint('x > 5', name=conv('ck_t_x5')))
+
+    Where above, the :func:`.schema.conv` marker indicates that the constraint
+    name here is final, and the name will render as ``"ck_t_x5"`` and not
+    ``"ck_t_ck_t_x5"``
+
+    .. versionadded:: 0.9.4
+
+    .. seealso::
+
+        :ref:`constraint_naming_conventions`
+
+    """
+
+
 class _defer_name(_truncated_label):
     """mark a name as 'deferred' for the purposes of automated name
     generation.
@@ -3210,6 +3256,8 @@ class _defer_name(_truncated_label):
     def __new__(cls, value):
         if value is None:
             return _NONE_NAME
+        elif isinstance(value, conv):
+            return value
         else:
             return super(_defer_name, cls).__new__(cls, value)
 
index eb017eb259305bb4e6f00d325faffb7ffcd381e9..053db3e340c4cbb2e965da4c92c1ad9dacbba1b9 100644 (file)
@@ -14,49 +14,9 @@ from .schema import Constraint, ForeignKeyConstraint, PrimaryKeyConstraint, \
                 UniqueConstraint, CheckConstraint, Index, Table, Column
 from .. import event, events
 from .. import exc
-from .elements import _truncated_label, _defer_name, _defer_none_name
+from .elements import _truncated_label, _defer_name, _defer_none_name, conv
 import re
 
-class conv(_truncated_label):
-    """Mark a string indicating that a name has already been converted
-    by a naming convention.
-
-    This is a string subclass that indicates a name that should not be
-    subject to any further naming conventions.
-
-    E.g. when we create a :class:`.Constraint` using a naming convention
-    as follows::
-
-        m = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"})
-        t = Table('t', m, Column('x', Integer),
-                        CheckConstraint('x > 5', name='x5'))
-
-    The name of the above constraint will be rendered as ``"ck_t_x5"``.  That is,
-    the existing name ``x5`` is used in the naming convention as the ``constraint_name``
-    token.
-
-    In some situations, such as in migration scripts, we may be rendering
-    the above :class:`.CheckConstraint` with a name that's already been
-    converted.  In order to make sure the name isn't double-modified, the
-    new name is applied using the :func:`.schema.conv` marker.  We can
-    use this explicitly as follows::
-
-
-        m = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"})
-        t = Table('t', m, Column('x', Integer),
-                        CheckConstraint('x > 5', name=conv('ck_t_x5')))
-
-    Where above, the :func:`.schema.conv` marker indicates that the constraint
-    name here is final, and the name will render as ``"ck_t_x5"`` and not
-    ``"ck_t_ck_t_x5"``
-
-    .. versionadded:: 0.9.4
-
-    .. seealso::
-
-        :ref:`constraint_naming_conventions`
-
-    """
 
 class ConventionDict(object):
     def __init__(self, const, table, convention):
@@ -147,7 +107,10 @@ def _get_convention(dict_, key):
 def _constraint_name_for_table(const, table):
     metadata = table.metadata
     convention = _get_convention(metadata.naming_convention, type(const))
-    if convention is not None and (
+
+    if isinstance(const.name, conv):
+        return const.name
+    elif convention is not None and (
             const.name is None or not isinstance(const.name, conv) and
                 "constraint_name" in convention
         ):
index ee7d372d79491e39f4dbb137710aba63e53e3400..8bd4199649451de16fe458d180550abafa619029 100644 (file)
@@ -2813,7 +2813,7 @@ class DialectKWArgTest(fixtures.TestBase):
 
 
 class NamingConventionTest(fixtures.TestBase, AssertsCompiledSQL):
-    dialect = 'default'
+    __dialect__ = 'default'
 
     def _fixture(self, naming_convention, table_schema=None):
         m1 = MetaData(naming_convention=naming_convention)
@@ -2957,7 +2957,7 @@ class NamingConventionTest(fixtures.TestBase, AssertsCompiledSQL):
         # but is hit at compile time
         self.assert_compile(
             schema.CreateTable(u1),
-            "CREATE TABLE user ("
+            'CREATE TABLE "user" ('
             "x BOOLEAN, "
             "CONSTRAINT ck_user_foo CHECK (x IN (0, 1))"
             ")"
@@ -2977,12 +2977,32 @@ class NamingConventionTest(fixtures.TestBase, AssertsCompiledSQL):
         # but is hit at compile time
         self.assert_compile(
             schema.CreateTable(u1),
-            "CREATE TABLE user ("
+            'CREATE TABLE "user" ('
                 "x VARCHAR(1), "
                 "CONSTRAINT ck_user_foo CHECK (x IN ('a', 'b'))"
             ")"
         )
 
+    def test_schematype_ck_name_propagate_conv(self):
+        m1 = MetaData(naming_convention={
+                            "ck": "ck_%(table_name)s_%(constraint_name)s"})
+
+        u1 = Table('user', m1,
+            Column('x', Enum('a', 'b', name=naming.conv('foo')))
+            )
+        eq_(
+            [c for c in u1.constraints
+                if isinstance(c, CheckConstraint)][0].name, "foo"
+        )
+        # but is hit at compile time
+        self.assert_compile(
+            schema.CreateTable(u1),
+            'CREATE TABLE "user" ('
+                "x VARCHAR(1), "
+                "CONSTRAINT foo CHECK (x IN ('a', 'b'))"
+            ")"
+        )
+
     def test_schematype_ck_name_boolean_no_name(self):
         m1 = MetaData(naming_convention={
             "ck": "ck_%(table_name)s_%(constraint_name)s"
@@ -3028,7 +3048,7 @@ class NamingConventionTest(fixtures.TestBase, AssertsCompiledSQL):
 
         self.assert_compile(
             schema.CreateTable(u1),
-            "CREATE TABLE user (x BOOLEAN, CHECK (x IN (0, 1)))"
+            'CREATE TABLE "user" (x BOOLEAN, CHECK (x IN (0, 1)))'
         )