diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-03-12 17:33:03 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-03-12 17:33:03 -0400 |
commit | 36792434c74dea43a0f10f5fe1cc45c4206f01ee (patch) | |
tree | 792749694902e82ef088d481fca7a1fa70f7410f | |
parent | a7ef7eccaacae5341bb03a58cc0538718c33c329 (diff) | |
download | sqlalchemy-36792434c74dea43a0f10f5fe1cc45c4206f01ee.tar.gz |
- Added a new feature :func:`.schema.conv`, the purpose of which is to
mark a constraint name as already having had a naming convention applied.
This token will be used by Alembic migrations as of Alembic 0.6.4
in order to render constraints in migration scripts with names marked
as already having been subject to a naming convention.
re: #2991
-rw-r--r-- | doc/build/changelog/changelog_09.rst | 9 | ||||
-rw-r--r-- | doc/build/core/constraints.rst | 1 | ||||
-rw-r--r-- | lib/sqlalchemy/schema.py | 3 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/naming.py | 50 |
4 files changed, 58 insertions, 5 deletions
diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst index 20a0b656d..10879e2ca 100644 --- a/doc/build/changelog/changelog_09.rst +++ b/doc/build/changelog/changelog_09.rst @@ -15,6 +15,15 @@ :version: 0.9.4 .. change:: + :tags: feature, sql + + Added a new feature :func:`.schema.conv`, the purpose of which is to + mark a constraint name as already having had a naming convention applied. + This token will be used by Alembic migrations as of Alembic 0.6.4 + in order to render constraints in migration scripts with names marked + as already having been subject to a naming convention. + + .. change:: :tags: bug, sql :paramref:`.MetaData.naming_convention` feature will now also diff --git a/doc/build/core/constraints.rst b/doc/build/core/constraints.rst index 3979631b0..580fbc0b6 100644 --- a/doc/build/core/constraints.rst +++ b/doc/build/core/constraints.rst @@ -459,6 +459,7 @@ Constraints API :members: :inherited-members: +.. autofunction:: sqlalchemy.schema.conv .. _schema_indexes: diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index 9e647e595..8556272a6 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -37,6 +37,9 @@ from .sql.schema import ( ) +from .sql.naming import conv + + from .sql.ddl import ( DDL, CreateTable, diff --git a/lib/sqlalchemy/sql/naming.py b/lib/sqlalchemy/sql/naming.py index 3ba7f5105..1c5fae193 100644 --- a/lib/sqlalchemy/sql/naming.py +++ b/lib/sqlalchemy/sql/naming.py @@ -16,13 +16,54 @@ from .. import exc from .elements import _truncated_label 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): self.const = const self._is_fk = isinstance(const, ForeignKeyConstraint) self.table = table self.convention = convention - self._const_name = const._orig_name = getattr(const, '_orig_name', const.name) + self._const_name = const.name def _key_table_name(self): return self.table.name @@ -41,9 +82,8 @@ class ConventionDict(object): "%(constraint_name)s token requires that " "constraint is explicitly named." ) - # they asked for a name that's derived from the existing - # name, so set the existing name to None - self.const.name = None + if not isinstance(self._const_name, conv): + self.const.name = None return self._const_name def _key_column_X_name(self, idx): @@ -118,7 +158,7 @@ def _constraint_name(const, table): metadata = table.metadata convention = _get_convention(metadata.naming_convention, type(const)) if convention is not None: - newname = _truncated_label( + newname = conv( convention % ConventionDict(const, table, metadata.naming_convention) ) if const.name is None: |