summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-07-17 19:01:06 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-07-17 19:01:06 -0400
commit60c2f405a244fdc8991c2a30a2617fc4adc51bbc (patch)
treef50651794d3164c048003813b6a0ad7c3e919242
parentbbe847d5b8932d9c113d659a2807678aa8777ea1 (diff)
downloadalembic-60c2f405a244fdc8991c2a30a2617fc4adc51bbc.tar.gz
- sublime blowing away trailing space
- changelog - fix this test - fix docs for new mysql 'primary'
-rw-r--r--CHANGES3
-rw-r--r--alembic/operations.py209
-rw-r--r--tests/test_mysql.py3
3 files changed, 111 insertions, 104 deletions
diff --git a/CHANGES b/CHANGES
index 938b23f..1656c19 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,9 @@
- Added year, month, day, hour, minute, second
variables to file_template. #59
+- Added 'primary' to the list of constraint types
+ recognized for MySQL drop_constraint().
+
0.3.5
=====
- [bug] Fixed issue whereby reflected server defaults
diff --git a/alembic/operations.py b/alembic/operations.py
index 1d59df3..2eef7cb 100644
--- a/alembic/operations.py
+++ b/alembic/operations.py
@@ -17,25 +17,25 @@ class Operations(object):
While :class:`.Operations` is normally configured as
part of the :meth:`.EnvironmentContext.run_migrations`
- method called from an ``env.py`` script, a standalone
+ method called from an ``env.py`` script, a standalone
:class:`.Operations` instance can be
made for use cases external to regular Alembic
migrations by passing in a :class:`.MigrationContext`::
-
+
from alembic.migration import MigrationContext
from alembic.operations import Operations
-
+
conn = myengine.connect()
ctx = MigrationContext.configure(conn)
op = Operations(ctx)
-
+
op.alter_column("t", "c", nullable=True)
-
+
"""
def __init__(self, migration_context):
"""Construct a new :class:`.Operations`
- :param migration_context: a :class:`.MigrationContext`
+ :param migration_context: a :class:`.MigrationContext`
instance.
"""
@@ -50,17 +50,17 @@ class Operations(object):
yield op
alembic.op._remove_proxy()
- def _foreign_key_constraint(self, name, source, referent,
+ def _foreign_key_constraint(self, name, source, referent,
local_cols, remote_cols,
onupdate=None, ondelete=None):
m = schema.MetaData()
- t1 = schema.Table(source, m,
+ t1 = schema.Table(source, m,
*[schema.Column(n, NULLTYPE) for n in local_cols])
- t2 = schema.Table(referent, m,
+ t2 = schema.Table(referent, m,
*[schema.Column(n, NULLTYPE) for n in remote_cols])
- f = schema.ForeignKeyConstraint(local_cols,
- ["%s.%s" % (referent, n)
+ f = schema.ForeignKeyConstraint(local_cols,
+ ["%s.%s" % (referent, n)
for n in remote_cols],
name=name,
onupdate=onupdate,
@@ -71,7 +71,7 @@ class Operations(object):
return f
def _unique_constraint(self, name, source, local_cols, **kw):
- t = schema.Table(source, schema.MetaData(),
+ t = schema.Table(source, schema.MetaData(),
*[schema.Column(n, NULLTYPE) for n in local_cols])
kw['name'] = name
uq = schema.UniqueConstraint(*[t.c[n] for n in local_cols], **kw)
@@ -81,7 +81,7 @@ class Operations(object):
return uq
def _check_constraint(self, name, source, condition, **kw):
- t = schema.Table(source, schema.MetaData(),
+ t = schema.Table(source, schema.MetaData(),
schema.Column('x', Integer))
ck = schema.CheckConstraint(condition, name=name, **kw)
t.append_constraint(ck)
@@ -146,7 +146,7 @@ class Operations(object):
schema=schema
)
- def alter_column(self, table_name, column_name,
+ def alter_column(self, table_name, column_name,
nullable=None,
server_default=False,
name=None,
@@ -155,7 +155,7 @@ class Operations(object):
existing_server_default=False,
existing_nullable=None,
):
- """Issue an "alter column" instruction using the
+ """Issue an "alter column" instruction using the
current migration context.
Generally, only that aspect of the column which
@@ -177,16 +177,16 @@ class Operations(object):
and :class:`~sqlalchemy.types.Enum` may also
add or drop constraints which accompany those
types on backends that don't support them natively.
- The ``existing_server_default`` argument is
+ The ``existing_server_default`` argument is
used in this case as well to remove a previous
constraint.
:param table_name: string name of the target table.
- :param column_name: string name of the target column,
+ :param column_name: string name of the target column,
as it exists before the operation begins.
:param nullable: Optional; specify ``True`` or ``False``
to alter the column's nullability.
- :param server_default: Optional; specify a string
+ :param server_default: Optional; specify a string
SQL expression, :func:`~sqlalchemy.sql.expression.text`,
or :class:`~sqlalchemy.schema.DefaultClause` to indicate
an alteration to the column's default value.
@@ -195,25 +195,25 @@ class Operations(object):
indicate the new name within a column rename operation.
:param type_: Optional; a :class:`~sqlalchemy.types.TypeEngine`
type object to specify a change to the column's type.
- For SQLAlchemy types that also indicate a constraint (i.e.
- :class:`~sqlalchemy.types.Boolean`,
- :class:`~sqlalchemy.types.Enum`),
+ For SQLAlchemy types that also indicate a constraint (i.e.
+ :class:`~sqlalchemy.types.Boolean`,
+ :class:`~sqlalchemy.types.Enum`),
the constraint is also generated.
- :param existing_type: Optional; a
+ :param existing_type: Optional; a
:class:`~sqlalchemy.types.TypeEngine`
type object to specify the previous type. This
- is required for all MySQL column alter operations that
+ is required for all MySQL column alter operations that
don't otherwise specify a new type, as well as for
when nullability is being changed on a SQL Server
- column. It is also used if the type is a so-called
+ column. It is also used if the type is a so-called
SQLlchemy "schema" type which
- may define a constraint (i.e.
- :class:`~sqlalchemy.types.Boolean`,
- :class:`~sqlalchemy.types.Enum`),
+ may define a constraint (i.e.
+ :class:`~sqlalchemy.types.Boolean`,
+ :class:`~sqlalchemy.types.Enum`),
so that the constraint can be dropped.
:param existing_server_default: Optional; The existing
- default value of the column. Required on MySQL if
- an existing default is not being changed; else MySQL
+ default value of the column. Required on MySQL if
+ an existing default is not being changed; else MySQL
removes the default.
:param existing_nullable: Optional; the existing nullability
of the column. Required on MySQL if the existing nullability
@@ -221,14 +221,14 @@ class Operations(object):
"""
if existing_type:
- t = self._table(table_name,
+ t = self._table(table_name,
schema.Column(column_name, existing_type)
)
for constraint in t.constraints:
if not isinstance(constraint, schema.PrimaryKeyConstraint):
self.impl.drop_constraint(constraint)
- self.impl.alter_column(table_name, column_name,
+ self.impl.alter_column(table_name, column_name,
nullable=nullable,
server_default=server_default,
name=name,
@@ -245,7 +245,7 @@ class Operations(object):
self.impl.add_constraint(constraint)
def add_column(self, table_name, column):
- """Issue an "add column" instruction using the current
+ """Issue an "add column" instruction using the current
migration context.
e.g.::
@@ -253,7 +253,7 @@ class Operations(object):
from alembic import op
from sqlalchemy import Column, String
- op.add_column('organization',
+ op.add_column('organization',
Column('name', String())
)
@@ -266,7 +266,7 @@ class Operations(object):
from alembic import op
from sqlalchemy import Column, INTEGER, ForeignKey
- op.add_column('organization',
+ op.add_column('organization',
Column('account_id', INTEGER, ForeignKey('accounts.id'))
)
@@ -275,7 +275,7 @@ class Operations(object):
default values to be created on the database side are
specified using the ``server_default`` parameter, and not
``default`` which only specifies Python-side defaults::
-
+
from alembic import op
from sqlalchemy import Column, TIMESTAMP, func
@@ -300,7 +300,7 @@ class Operations(object):
self.impl.add_constraint(constraint)
def drop_column(self, table_name, column_name, **kw):
- """Issue a "drop column" instruction using the current
+ """Issue a "drop column" instruction using the current
migration context.
e.g.::
@@ -309,15 +309,15 @@ class Operations(object):
:param table_name: name of table
:param column_name: name of column
- :param mssql_drop_check: Optional boolean. When ``True``, on
- Microsoft SQL Server only, first
- drop the CHECK constraint on the column using a
+ :param mssql_drop_check: Optional boolean. When ``True``, on
+ Microsoft SQL Server only, first
+ drop the CHECK constraint on the column using a
SQL-script-compatible
block that selects into a @variable from sys.check_constraints,
then exec's a separate DROP CONSTRAINT for that constraint.
- :param mssql_drop_default: Optional boolean. When ``True``, on
- Microsoft SQL Server only, first
- drop the DEFAULT constraint on the column using a
+ :param mssql_drop_default: Optional boolean. When ``True``, on
+ Microsoft SQL Server only, first
+ drop the DEFAULT constraint on the column using a
SQL-script-compatible
block that selects into a @variable from sys.default_constraints,
then exec's a separate DROP CONSTRAINT for that default.
@@ -331,30 +331,30 @@ class Operations(object):
)
- def create_foreign_key(self, name, source, referent, local_cols,
+ def create_foreign_key(self, name, source, referent, local_cols,
remote_cols, onupdate=None, ondelete=None):
- """Issue a "create foreign key" instruction using the
+ """Issue a "create foreign key" instruction using the
current migration context.
e.g.::
from alembic import op
op.create_foreign_key(
- "fk_user_address", "address",
+ "fk_user_address", "address",
"user", ["user_id"], ["id"])
This internally generates a :class:`~sqlalchemy.schema.Table` object
- containing the necessary columns, then generates a new
+ containing the necessary columns, then generates a new
:class:`~sqlalchemy.schema.ForeignKeyConstraint`
object which it then associates with the :class:`~sqlalchemy.schema.Table`.
- Any event listeners associated with this action will be fired
+ Any event listeners associated with this action will be fired
off normally. The :class:`~sqlalchemy.schema.AddConstraint`
construct is ultimately used to generate the ALTER statement.
:param name: Name of the foreign key constraint. The name is necessary
so that an ALTER statement can be emitted. For setups that
use an automated naming scheme such as that described at
- `NamingConventions <http://www.sqlalchemy.org/trac/wiki/UsageRecipes/NamingConventions>`_,
+ `NamingConventions <http://www.sqlalchemy.org/trac/wiki/UsageRecipes/NamingConventions>`_,
``name`` here can be ``None``, as the event listener will
apply the name to the constraint object when it is associated
with the table.
@@ -362,7 +362,7 @@ class Operations(object):
there is no support for dotted schema names.
:param referent: String name of the destination table. Currently
there is no support for dotted schema names.
- :param local_cols: a list of string column names in the
+ :param local_cols: a list of string column names in the
source table.
:param remote_cols: a list of string column names in the
remote table.
@@ -376,13 +376,13 @@ class Operations(object):
"""
self.impl.add_constraint(
- self._foreign_key_constraint(name, source, referent,
+ self._foreign_key_constraint(name, source, referent,
local_cols, remote_cols,
onupdate=onupdate, ondelete=ondelete)
)
def create_unique_constraint(self, name, source, local_cols, **kw):
- """Issue a "create unique constraint" instruction using the
+ """Issue a "create unique constraint" instruction using the
current migration context.
e.g.::
@@ -391,23 +391,23 @@ class Operations(object):
op.create_unique_constraint("uq_user_name", "user", ["name"])
This internally generates a :class:`~sqlalchemy.schema.Table` object
- containing the necessary columns, then generates a new
+ containing the necessary columns, then generates a new
:class:`~sqlalchemy.schema.UniqueConstraint`
object which it then associates with the :class:`~sqlalchemy.schema.Table`.
- Any event listeners associated with this action will be fired
+ Any event listeners associated with this action will be fired
off normally. The :class:`~sqlalchemy.schema.AddConstraint`
construct is ultimately used to generate the ALTER statement.
:param name: Name of the unique constraint. The name is necessary
so that an ALTER statement can be emitted. For setups that
use an automated naming scheme such as that described at
- `NamingConventions <http://www.sqlalchemy.org/trac/wiki/UsageRecipes/NamingConventions>`_,
+ `NamingConventions <http://www.sqlalchemy.org/trac/wiki/UsageRecipes/NamingConventions>`_,
``name`` here can be ``None``, as the event listener will
apply the name to the constraint object when it is associated
with the table.
:param source: String name of the source table. Currently
there is no support for dotted schema names.
- :param local_cols: a list of string column names in the
+ :param local_cols: a list of string column names in the
source table.
:param deferrable: optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when
issuing DDL for this constraint.
@@ -417,12 +417,12 @@ class Operations(object):
"""
self.impl.add_constraint(
- self._unique_constraint(name, source, local_cols,
+ self._unique_constraint(name, source, local_cols,
**kw)
)
def create_check_constraint(self, name, source, condition, **kw):
- """Issue a "create check constraint" instruction using the
+ """Issue a "create check constraint" instruction using the
current migration context.
e.g.::
@@ -432,19 +432,19 @@ class Operations(object):
op.create_check_constraint(
"ck_user_name_len",
- "user",
+ "user",
func.len(column('name')) > 5
)
CHECK constraints are usually against a SQL expression, so ad-hoc
- table metadata is usually needed. The function will convert the given
- arguments into a :class:`sqlalchemy.schema.CheckConstraint` bound
+ table metadata is usually needed. The function will convert the given
+ arguments into a :class:`sqlalchemy.schema.CheckConstraint` bound
to an anonymous table in order to emit the CREATE statement.
:param name: Name of the check constraint. The name is necessary
so that an ALTER statement can be emitted. For setups that
use an automated naming scheme such as that described at
- `NamingConventions <http://www.sqlalchemy.org/trac/wiki/UsageRecipes/NamingConventions>`_,
+ `NamingConventions <http://www.sqlalchemy.org/trac/wiki/UsageRecipes/NamingConventions>`_,
``name`` here can be ``None``, as the event listener will
apply the name to the constraint object when it is associated
with the table.
@@ -465,7 +465,7 @@ class Operations(object):
def create_table(self, name, *columns, **kw):
"""Issue a "create table" instruction using the current migration context.
- This directive receives an argument list similar to that of the
+ This directive receives an argument list similar to that of the
traditional :class:`sqlalchemy.schema.Table` construct, but without the
metadata::
@@ -485,7 +485,7 @@ class Operations(object):
default values to be created on the database side are
specified using the ``server_default`` parameter, and not
``default`` which only specifies Python-side defaults::
-
+
from alembic import op
from sqlalchemy import Column, TIMESTAMP, func
@@ -496,14 +496,14 @@ class Operations(object):
)
:param name: Name of the table
- :param \*columns: collection of :class:`~sqlalchemy.schema.Column`
+ :param \*columns: collection of :class:`~sqlalchemy.schema.Column`
objects within
- the table, as well as optional :class:`~sqlalchemy.schema.Constraint`
+ the table, as well as optional :class:`~sqlalchemy.schema.Constraint`
objects
and :class:`~.sqlalchemy.schema.Index` objects.
- :param emit_events: if ``True``, emit ``before_create`` and
- ``after_create`` events when the table is being created. In
- particular, the Postgresql ENUM type will emit a CREATE TYPE within
+ :param emit_events: if ``True``, emit ``before_create`` and
+ ``after_create`` events when the table is being created. In
+ particular, the Postgresql ENUM type will emit a CREATE TYPE within
these events.
:param \**kw: Other keyword arguments are passed to the underlying
:class:`.Table` object created for the command.
@@ -514,7 +514,7 @@ class Operations(object):
)
def drop_table(self, name):
- """Issue a "drop table" instruction using the current
+ """Issue a "drop table" instruction using the current
migration context.
@@ -528,7 +528,7 @@ class Operations(object):
)
def create_index(self, name, tablename, *columns, **kw):
- """Issue a "create index" instruction using the current
+ """Issue a "create index" instruction using the current
migration context.
e.g.::
@@ -543,14 +543,14 @@ class Operations(object):
)
def drop_index(self, name, tablename=None):
- """Issue a "drop index" instruction using the current
+ """Issue a "drop index" instruction using the current
migration context.
e.g.::
drop_index("accounts")
-
+
:param tablename: name of the owning table. Some
backends such as Microsoft SQL Server require this.
@@ -561,18 +561,21 @@ class Operations(object):
def drop_constraint(self, name, tablename, type=None):
"""Drop a constraint of the given name, typically via DROP CONSTRAINT.
-
+
:param name: name of the constraint.
:param tablename: tablename.
- :param type: optional, required on MySQL. can be
- 'foreignkey', 'primary', 'unique', or 'check'
+ :param type: optional, required on MySQL. can be
+ 'foreignkey', 'primary', 'unique', or 'check'.
+
+ .. versionadded:: 0.3.6 'primary' qualfier to enable
+ dropping of MySQL primary key constraints.
"""
t = self._table(tablename)
types = {
'foreignkey':lambda name:schema.ForeignKeyConstraint(
[], [], name=name),
- 'primary':schema.PrimaryKeyConstraint,
+ 'primary':schema.PrimaryKeyConstraint,
'unique':schema.UniqueConstraint,
'check':lambda name:schema.CheckConstraint("", name=name),
None:schema.Constraint
@@ -580,21 +583,21 @@ class Operations(object):
try:
const = types[type]
except KeyError:
- raise TypeError("'type' can be one of %s" %
- ", ".join(sorted(repr(x) for x in types)))
+ raise TypeError("'type' can be one of %s" %
+ ", ".join(sorted(repr(x) for x in types)))
const = const(name=name)
t.append_constraint(const)
self.impl.drop_constraint(const)
def bulk_insert(self, table, rows):
- """Issue a "bulk insert" operation using the current
+ """Issue a "bulk insert" operation using the current
migration context.
This provides a means of representing an INSERT of multiple rows
- which works equally well in the context of executing on a live
- connection as well as that of generating a SQL script. In the
- case of a SQL script, the values are rendered inline into the
+ which works equally well in the context of executing on a live
+ connection as well as that of generating a SQL script. In the
+ case of a SQL script, the values are rendered inline into the
statement.
e.g.::
@@ -612,11 +615,11 @@ class Operations(object):
bulk_insert(accounts_table,
[
- {'id':1, 'name':'John Smith',
+ {'id':1, 'name':'John Smith',
'create_date':date(2010, 10, 5)},
- {'id':2, 'name':'Ed Williams',
+ {'id':2, 'name':'Ed Williams',
'create_date':date(2007, 5, 27)},
- {'id':3, 'name':'Wendy Jones',
+ {'id':3, 'name':'Wendy Jones',
'create_date':date(2008, 8, 15)},
]
)
@@ -624,7 +627,7 @@ class Operations(object):
self.impl.bulk_insert(table, rows)
def inline_literal(self, value, type_=None):
- """Produce an 'inline literal' expression, suitable for
+ """Produce an 'inline literal' expression, suitable for
using in an INSERT, UPDATE, or DELETE statement.
When using Alembic in "offline" mode, CRUD operations
@@ -636,7 +639,7 @@ class Operations(object):
script needs to have these rendered inline. While it should
always be noted that inline literal values are an **enormous**
security hole in an application that handles untrusted input,
- a schema migration is not run in this context, so
+ a schema migration is not run in this context, so
literals are safe to render inline, with the caveat that
advanced types like dates may not be supported directly
by SQLAlchemy.
@@ -646,10 +649,10 @@ class Operations(object):
:param value: The value to render. Strings, integers, and simple
numerics should be supported. Other types like boolean,
- dates, etc. may or may not be supported yet by various
+ dates, etc. may or may not be supported yet by various
backends.
- :param type_: optional - a :class:`sqlalchemy.types.TypeEngine`
- subclass stating the type of this value. In SQLAlchemy
+ :param type_: optional - a :class:`sqlalchemy.types.TypeEngine`
+ subclass stating the type of this value. In SQLAlchemy
expressions, this is usually derived automatically
from the Python type of the value itself, as well as
based on the context in which the value is used.
@@ -660,11 +663,11 @@ class Operations(object):
def execute(self, sql, execution_options=None):
"""Execute the given SQL using the current migration context.
- In a SQL script context, the statement is emitted directly to the
+ In a SQL script context, the statement is emitted directly to the
output stream. There is *no* return result, however, as this
function is oriented towards generating a change script
that can run in "offline" mode. For full interaction
- with a connected database, use the "bind" available
+ with a connected database, use the "bind" available
from the context::
from alembic import op
@@ -673,9 +676,9 @@ class Operations(object):
Also note that any parameterized statement here *will not work*
in offline mode - INSERT, UPDATE and DELETE statements which refer
to literal values would need to render
- inline expressions. For simple use cases, the
- :meth:`.inline_literal` function can be used for **rudimentary**
- quoting of string values. For "bulk" inserts, consider using
+ inline expressions. For simple use cases, the
+ :meth:`.inline_literal` function can be used for **rudimentary**
+ quoting of string values. For "bulk" inserts, consider using
:meth:`.bulk_insert`.
For example, to emit an UPDATE statement which is equally
@@ -685,7 +688,7 @@ class Operations(object):
from sqlalchemy import String
from alembic import op
- account = table('account',
+ account = table('account',
column('name', String)
)
op.execute(
@@ -694,7 +697,7 @@ class Operations(object):
values({'name':op.inline_literal('account 2')})
)
- Note above we also used the SQLAlchemy
+ Note above we also used the SQLAlchemy
:func:`sqlalchemy.sql.expression.table`
and :func:`sqlalchemy.sql.expression.column` constructs to make a brief,
ad-hoc table construct just for our UPDATE statement. A full
@@ -709,23 +712,23 @@ class Operations(object):
* a string
* a :func:`sqlalchemy.sql.expression.text` construct.
* a :func:`sqlalchemy.sql.expression.insert` construct.
- * a :func:`sqlalchemy.sql.expression.update`,
- :func:`sqlalchemy.sql.expression.insert`,
+ * a :func:`sqlalchemy.sql.expression.update`,
+ :func:`sqlalchemy.sql.expression.insert`,
or :func:`sqlalchemy.sql.expression.delete` construct.
* Pretty much anything that's "executable" as described
in :ref:`sqlexpression_toplevel`.
- :param execution_options: Optional dictionary of
- execution options, will be passed to
+ :param execution_options: Optional dictionary of
+ execution options, will be passed to
:meth:`sqlalchemy.engine.base.Connection.execution_options`.
"""
- self.migration_context.impl.execute(sql,
+ self.migration_context.impl.execute(sql,
execution_options=execution_options)
def get_bind(self):
"""Return the current 'bind'.
- Under normal circumstances, this is the
+ Under normal circumstances, this is the
:class:`~sqlalchemy.engine.base.Connection` currently being used
to emit SQL to the database.
diff --git a/tests/test_mysql.py b/tests/test_mysql.py
index 548217e..a47ef9d 100644
--- a/tests/test_mysql.py
+++ b/tests/test_mysql.py
@@ -74,7 +74,8 @@ def test_drop_unknown():
context = op_fixture('mysql')
assert_raises_message(
TypeError,
- "'type' can be one of 'check', 'foreignkey', 'unique', None",
+ "'type' can be one of 'check', 'foreignkey', "
+ "'primary', 'unique', None",
op.drop_constraint, "f1", "t1", "typo"
)