- move to 0.5.0 as we are making some slight naming changes
- add a generalized approach for renamed kw args, accepting the old ones using a specialized decorator - change "tablename" to "table_name" for create_index, drop_index, drop_constraint - change "name" to "new_column_name" for alter_column #104
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from os import path
|
||||
|
||||
__version__ = '0.4.3'
|
||||
__version__ = '0.5.0'
|
||||
|
||||
package_dir = path.abspath(path.dirname(__file__))
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from alembic import util
|
||||
from alembic.ddl import impl
|
||||
from sqlalchemy.types import NULLTYPE, Integer
|
||||
from sqlalchemy import schema as sa_schema, sql
|
||||
from sqlalchemy import schema as sa_schema
|
||||
from contextlib import contextmanager
|
||||
import alembic
|
||||
|
||||
@@ -162,10 +162,11 @@ class Operations(object):
|
||||
schema=schema
|
||||
)
|
||||
|
||||
@util._with_legacy_names([('name', 'new_column_name')])
|
||||
def alter_column(self, table_name, column_name,
|
||||
nullable=None,
|
||||
server_default=False,
|
||||
name=None,
|
||||
new_column_name=None,
|
||||
type_=None,
|
||||
autoincrement=None,
|
||||
existing_type=None,
|
||||
@@ -210,8 +211,14 @@ class Operations(object):
|
||||
or :class:`~sqlalchemy.schema.DefaultClause` to indicate
|
||||
an alteration to the column's default value.
|
||||
Set to ``None`` to have the default removed.
|
||||
:param name: Optional; specify a string name here to
|
||||
:param new_column_name: Optional; specify a string name here to
|
||||
indicate the new name within a column rename operation.
|
||||
|
||||
.. versionchanged:: 0.5.0
|
||||
The ``name`` parameter is now named ``new_column_name``.
|
||||
The old name will continue to function for backwards
|
||||
compatibility.
|
||||
|
||||
: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.
|
||||
@@ -267,7 +274,7 @@ class Operations(object):
|
||||
self.impl.alter_column(table_name, column_name,
|
||||
nullable=nullable,
|
||||
server_default=server_default,
|
||||
name=name,
|
||||
name=new_column_name,
|
||||
type_=type_,
|
||||
schema=schema,
|
||||
autoincrement=autoincrement,
|
||||
@@ -592,7 +599,7 @@ class Operations(object):
|
||||
self._table(name, **kw)
|
||||
)
|
||||
|
||||
def create_index(self, name, tablename, columns, schema=None, **kw):
|
||||
def create_index(self, name, table_name, columns, schema=None, **kw):
|
||||
"""Issue a "create index" instruction using the current
|
||||
migration context.
|
||||
|
||||
@@ -602,7 +609,13 @@ class Operations(object):
|
||||
op.create_index('ik_test', 't1', ['foo', 'bar'])
|
||||
|
||||
:param name: name of the index.
|
||||
:param tablename: name of the owning table.
|
||||
:param table_name: name of the owning table.
|
||||
|
||||
.. versionchanged:: 0.5.0
|
||||
The ``tablename`` parameter is now named ``table_name``.
|
||||
As this is a positional argument, the old name is no
|
||||
longer present.
|
||||
|
||||
:param columns: a list of string column names in the
|
||||
table.
|
||||
:param schema: Optional schema name to operate within.
|
||||
@@ -612,21 +625,27 @@ class Operations(object):
|
||||
"""
|
||||
|
||||
self.impl.create_index(
|
||||
self._index(name, tablename, columns, schema=schema, **kw)
|
||||
self._index(name, table_name, columns, schema=schema, **kw)
|
||||
)
|
||||
|
||||
def drop_index(self, name, tablename=None, schema=None):
|
||||
@util._with_legacy_names([('tablename', 'table_name')])
|
||||
def drop_index(self, name, table_name=None, schema=None):
|
||||
"""Issue a "drop index" instruction using the current
|
||||
migration context.
|
||||
|
||||
|
||||
e.g.::
|
||||
|
||||
drop_index("accounts")
|
||||
|
||||
:param name: name of the index.
|
||||
:param tablename: name of the owning table. Some
|
||||
:param table_name: name of the owning table. Some
|
||||
backends such as Microsoft SQL Server require this.
|
||||
|
||||
.. versionchanged:: 0.5.0
|
||||
The ``tablename`` parameter is now named ``table_name``.
|
||||
The old name will continue to function for backwards
|
||||
compatibility.
|
||||
|
||||
:param schema: Optional schema name to operate within.
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
@@ -635,43 +654,45 @@ class Operations(object):
|
||||
# need a dummy column name here since SQLAlchemy
|
||||
# 0.7.6 and further raises on Index with no columns
|
||||
self.impl.drop_index(
|
||||
self._index(name, tablename, ['x'], schema=schema)
|
||||
self._index(name, table_name, ['x'], schema=schema)
|
||||
)
|
||||
|
||||
def drop_constraint(self, name, tablename, type_=None, schema=None, type=None):
|
||||
@util._with_legacy_names([("type", "type_")])
|
||||
def drop_constraint(self, name, table_name, type_=None, schema=None):
|
||||
"""Drop a constraint of the given name, typically via DROP CONSTRAINT.
|
||||
|
||||
:param name: name of the constraint.
|
||||
:param tablename: tablename.
|
||||
:param table_name: table name.
|
||||
|
||||
.. versionchanged:: 0.5.0
|
||||
The ``tablename`` parameter is now named ``table_name``.
|
||||
As this is a positional argument, the old name is no
|
||||
longer present.
|
||||
|
||||
:param ``type_``: optional, required on MySQL. can be
|
||||
'foreignkey', 'primary', 'unique', or 'check'.
|
||||
|
||||
.. versionadded:: 0.4.2 the parameter is now named ``type_``.
|
||||
.. versionchanged:: 0.5.0
|
||||
The ``type`` parameter is now named ``type_``. The old name
|
||||
``type`` will remain for backwards compatibility.
|
||||
|
||||
.. versionadded:: 0.3.6 'primary' qualfier to enable
|
||||
dropping of MySQL primary key constraints.
|
||||
|
||||
:param type: deprecated, use ``type_``.
|
||||
|
||||
.. versionchanged:: 0.4.2
|
||||
|
||||
:param schema: Optional schema name to operate within.
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
"""
|
||||
if type and type_ is None:
|
||||
type_ = type
|
||||
|
||||
t = self._table(tablename, schema=schema)
|
||||
t = self._table(table_name, schema=schema)
|
||||
types = {
|
||||
'foreignkey':lambda name:sa_schema.ForeignKeyConstraint(
|
||||
'foreignkey': lambda name: sa_schema.ForeignKeyConstraint(
|
||||
[], [], name=name),
|
||||
'primary':sa_schema.PrimaryKeyConstraint,
|
||||
'unique':sa_schema.UniqueConstraint,
|
||||
'check':lambda name:sa_schema.CheckConstraint("", name=name),
|
||||
None:sa_schema.Constraint
|
||||
'primary': sa_schema.PrimaryKeyConstraint,
|
||||
'unique': sa_schema.UniqueConstraint,
|
||||
'check': lambda name: sa_schema.CheckConstraint("", name=name),
|
||||
None: sa_schema.Constraint
|
||||
}
|
||||
try:
|
||||
const = types[type_]
|
||||
|
||||
@@ -5,14 +5,12 @@ import sys
|
||||
import os
|
||||
import textwrap
|
||||
from sqlalchemy.engine import url
|
||||
from sqlalchemy import util as sqla_util
|
||||
import imp
|
||||
import warnings
|
||||
import re
|
||||
import inspect
|
||||
import time
|
||||
import random
|
||||
import uuid
|
||||
from sqlalchemy.util import format_argspec_plus, update_wrapper
|
||||
|
||||
class CommandError(Exception):
|
||||
pass
|
||||
@@ -251,3 +249,44 @@ class immutabledict(dict):
|
||||
|
||||
def __repr__(self):
|
||||
return "immutabledict(%s)" % dict.__repr__(self)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def _with_legacy_names(translations):
|
||||
def decorate(fn):
|
||||
spec = inspect.getargspec(fn)
|
||||
metadata = dict(target='target', fn='fn')
|
||||
metadata.update(format_argspec_plus(spec, grouped=False))
|
||||
|
||||
has_keywords = bool(spec[2])
|
||||
|
||||
if not has_keywords:
|
||||
metadata['args'] += ", **kw"
|
||||
metadata['apply_kw'] += ", **kw"
|
||||
|
||||
def go(*arg, **kw):
|
||||
names = set(kw).difference(spec[0])
|
||||
for oldname, newname in translations:
|
||||
if oldname in kw:
|
||||
kw[newname] = kw.pop(oldname)
|
||||
names.discard(oldname)
|
||||
|
||||
warnings.warn(
|
||||
"Argument '%s' is now named '%s' for function '%s'" %
|
||||
(oldname, newname, fn.__name__))
|
||||
if not has_keywords and names:
|
||||
raise TypeError("Unknown arguments: %s" % ", ".join(names))
|
||||
return fn(*arg, **kw)
|
||||
|
||||
code = 'lambda %(args)s: %(target)s(%(apply_kw)s)' % (
|
||||
metadata)
|
||||
decorated = eval(code, {"target": go})
|
||||
decorated.func_defaults = getattr(fn, 'im_func', fn).func_defaults
|
||||
return update_wrapper(decorated, fn)
|
||||
|
||||
return decorate
|
||||
|
||||
|
||||
|
||||
|
||||
28
docs/build/changelog.rst
vendored
28
docs/build/changelog.rst
vendored
@@ -4,15 +4,31 @@ Changelog
|
||||
==========
|
||||
|
||||
.. changelog::
|
||||
:version: 0.4.3
|
||||
:version: 0.5.0
|
||||
|
||||
.. change::
|
||||
:tags: bug, documentation
|
||||
:tags: bug
|
||||
:tickets: 104
|
||||
|
||||
The name of the "type" parameter on :func:`.drop_constraint`
|
||||
is now officially named ``type_`` for consistency.
|
||||
``type`` will remain in at least the near future for
|
||||
backwards compatibility.
|
||||
A host of argument name changes within migration
|
||||
operations for consistency. Keyword arguments
|
||||
will continue to work on the old name for backwards compatibility,
|
||||
however required positional arguments will not:
|
||||
|
||||
:meth:`.Operations.alter_column` - ``name`` -> ``new_column_name`` - old
|
||||
name will work for backwards compatibility.
|
||||
|
||||
:meth:`.Operations.create_index` - ``tablename`` -> ``table_name`` -
|
||||
argument is positional.
|
||||
|
||||
:meth:`.Operations.drop_index` - ``tablename`` -> ``table_name`` - old
|
||||
name will work for backwards compatibility.
|
||||
|
||||
:meth:`.Operations.drop_constraint` - ``tablename`` -> ``table_name`` -
|
||||
argument is positional.
|
||||
|
||||
:meth:`.Operations.drop_constraint` - ``type`` -> ``type_`` - old
|
||||
name will work for backwards compatibility
|
||||
|
||||
.. changelog::
|
||||
:version: 0.4.2
|
||||
|
||||
@@ -53,7 +53,7 @@ class OpTest(TestCase):
|
||||
|
||||
def test_alter_column_rename_mssql(self):
|
||||
context = op_fixture('mssql')
|
||||
op.alter_column("t", "c", name="x")
|
||||
op.alter_column("t", "c", new_column_name="x")
|
||||
context.assert_(
|
||||
"EXEC sp_rename 't.c', 'x', 'COLUMN'"
|
||||
)
|
||||
@@ -154,7 +154,8 @@ class OpTest(TestCase):
|
||||
|
||||
def test_alter_do_everything(self):
|
||||
context = op_fixture('mssql')
|
||||
op.alter_column("t", "c", name="c2", nullable=True, type_=Integer, server_default="5")
|
||||
op.alter_column("t", "c", new_column_name="c2", nullable=True,
|
||||
type_=Integer, server_default="5")
|
||||
context.assert_(
|
||||
'ALTER TABLE t ALTER COLUMN c INTEGER NULL',
|
||||
"ALTER TABLE t ADD DEFAULT '5' FOR c",
|
||||
|
||||
@@ -3,25 +3,25 @@ from alembic import op, util
|
||||
from sqlalchemy import Integer, Column, ForeignKey, \
|
||||
UniqueConstraint, Table, MetaData, String,\
|
||||
func
|
||||
from sqlalchemy.sql import table
|
||||
|
||||
def test_rename_column():
|
||||
context = op_fixture('mysql')
|
||||
op.alter_column('t1', 'c1', name="c2", existing_type=Integer)
|
||||
op.alter_column('t1', 'c1', new_column_name="c2", existing_type=Integer)
|
||||
context.assert_(
|
||||
'ALTER TABLE t1 CHANGE c1 c2 INTEGER NULL'
|
||||
)
|
||||
|
||||
def test_rename_column_serv_default():
|
||||
context = op_fixture('mysql')
|
||||
op.alter_column('t1', 'c1', name="c2", existing_type=Integer, existing_server_default="q")
|
||||
op.alter_column('t1', 'c1', new_column_name="c2", existing_type=Integer,
|
||||
existing_server_default="q")
|
||||
context.assert_(
|
||||
"ALTER TABLE t1 CHANGE c1 c2 INTEGER NULL DEFAULT 'q'"
|
||||
)
|
||||
|
||||
def test_rename_column_serv_compiled_default():
|
||||
context = op_fixture('mysql')
|
||||
op.alter_column('t1', 'c1', name="c2", existing_type=Integer,
|
||||
op.alter_column('t1', 'c1', new_column_name="c2", existing_type=Integer,
|
||||
existing_server_default=func.utc_thing(func.current_timestamp()))
|
||||
# this is not a valid MySQL default but the point is to just
|
||||
# test SQL expression rendering
|
||||
@@ -31,7 +31,7 @@ def test_rename_column_serv_compiled_default():
|
||||
|
||||
def test_rename_column_autoincrement():
|
||||
context = op_fixture('mysql')
|
||||
op.alter_column('t1', 'c1', name="c2", existing_type=Integer,
|
||||
op.alter_column('t1', 'c1', new_column_name="c2", existing_type=Integer,
|
||||
existing_autoincrement=True)
|
||||
context.assert_(
|
||||
'ALTER TABLE t1 CHANGE c1 c2 INTEGER NULL AUTO_INCREMENT'
|
||||
@@ -39,7 +39,7 @@ def test_rename_column_autoincrement():
|
||||
|
||||
def test_col_add_autoincrement():
|
||||
context = op_fixture('mysql')
|
||||
op.alter_column('t1', 'c1', name="c2", existing_type=Integer,
|
||||
op.alter_column('t1', 'c1', new_column_name="c2", existing_type=Integer,
|
||||
autoincrement=True)
|
||||
context.assert_(
|
||||
'ALTER TABLE t1 CHANGE c1 c2 INTEGER NULL AUTO_INCREMENT'
|
||||
@@ -47,7 +47,7 @@ def test_col_add_autoincrement():
|
||||
|
||||
def test_col_remove_autoincrement():
|
||||
context = op_fixture('mysql')
|
||||
op.alter_column('t1', 'c1', name="c2", existing_type=Integer,
|
||||
op.alter_column('t1', 'c1', new_column_name="c2", existing_type=Integer,
|
||||
existing_autoincrement=True,
|
||||
autoincrement=False)
|
||||
context.assert_(
|
||||
@@ -86,7 +86,7 @@ def test_drop_fk():
|
||||
|
||||
def test_drop_constraint_primary():
|
||||
context = op_fixture('mysql')
|
||||
op.drop_constraint('primary', 't1',type='primary')
|
||||
op.drop_constraint('primary', 't1', type_='primary')
|
||||
context.assert_(
|
||||
"ALTER TABLE t1 DROP PRIMARY KEY "
|
||||
)
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
from tests import op_fixture, assert_raises_message
|
||||
from alembic import op
|
||||
from sqlalchemy import Integer, Column, ForeignKey, \
|
||||
UniqueConstraint, Table, MetaData, String,\
|
||||
Boolean
|
||||
from sqlalchemy.sql import table, column, func
|
||||
Table, String, Boolean
|
||||
from sqlalchemy.sql import column, func
|
||||
|
||||
|
||||
def test_rename_table():
|
||||
@@ -169,14 +168,14 @@ def test_alter_column_schema_not_nullable():
|
||||
|
||||
def test_alter_column_rename():
|
||||
context = op_fixture()
|
||||
op.alter_column("t", "c", name="x")
|
||||
op.alter_column("t", "c", new_column_name="x")
|
||||
context.assert_(
|
||||
"ALTER TABLE t RENAME c TO x"
|
||||
)
|
||||
|
||||
def test_alter_column_schema_rename():
|
||||
context = op_fixture()
|
||||
op.alter_column("t", "c", name="x", schema='foo')
|
||||
op.alter_column("t", "c", new_column_name="x", schema='foo')
|
||||
context.assert_(
|
||||
"ALTER TABLE foo.t RENAME c TO x"
|
||||
)
|
||||
@@ -550,13 +549,13 @@ def test_inline_literal():
|
||||
)
|
||||
op.execute(
|
||||
account.update().\
|
||||
where(account.c.name==op.inline_literal('account 1')).\
|
||||
values({'name':op.inline_literal('account 2')})
|
||||
where(account.c.name == op.inline_literal('account 1')).\
|
||||
values({'name': op.inline_literal('account 2')})
|
||||
)
|
||||
op.execute(
|
||||
account.update().\
|
||||
where(account.c.id==op.inline_literal(1)).\
|
||||
values({'id':op.inline_literal(2)})
|
||||
where(account.c.id == op.inline_literal(1)).\
|
||||
values({'id': op.inline_literal(2)})
|
||||
)
|
||||
context.assert_(
|
||||
"UPDATE account SET name='account 2' WHERE account.name = 'account 1'",
|
||||
@@ -574,3 +573,36 @@ def test_cant_op():
|
||||
"Try placing this code inside a callable.",
|
||||
op.inline_literal, "asdf"
|
||||
)
|
||||
|
||||
|
||||
def test_naming_changes():
|
||||
context = op_fixture()
|
||||
op.alter_column("t", "c", name="x")
|
||||
context.assert_("ALTER TABLE t RENAME c TO x")
|
||||
|
||||
context = op_fixture()
|
||||
op.alter_column("t", "c", new_column_name="x")
|
||||
context.assert_("ALTER TABLE t RENAME c TO x")
|
||||
|
||||
context = op_fixture('mssql')
|
||||
op.drop_index('ik_test', tablename='t1')
|
||||
context.assert_("DROP INDEX [t1].ik_test")
|
||||
|
||||
context = op_fixture('mssql')
|
||||
op.drop_index('ik_test', table_name='t1')
|
||||
context.assert_("DROP INDEX [t1].ik_test")
|
||||
|
||||
context = op_fixture('mysql')
|
||||
op.drop_constraint("f1", "t1", type="foreignkey")
|
||||
context.assert_("ALTER TABLE t1 DROP FOREIGN KEY f1")
|
||||
|
||||
context = op_fixture('mysql')
|
||||
op.drop_constraint("f1", "t1", type_="foreignkey")
|
||||
context.assert_("ALTER TABLE t1 DROP FOREIGN KEY f1")
|
||||
|
||||
assert_raises_message(
|
||||
TypeError,
|
||||
"Unknown arguments: badarg2, badarg1",
|
||||
op.alter_column, "t", "c", badarg1="x", badarg2="y"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user