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 /lib/sqlalchemy/sql/naming.py | |
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
Diffstat (limited to 'lib/sqlalchemy/sql/naming.py')
-rw-r--r-- | lib/sqlalchemy/sql/naming.py | 50 |
1 files changed, 45 insertions, 5 deletions
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: |