]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
- move to 0.5.0 as we are making some slight naming changes
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 11 Feb 2013 19:37:59 +0000 (14:37 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 11 Feb 2013 19:37:59 +0000 (14:37 -0500)
- 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

alembic/__init__.py
alembic/operations.py
alembic/util.py
docs/build/changelog.rst
tests/test_mssql.py
tests/test_mysql.py
tests/test_op.py

index 2ca08edbb293c5035a6affce6fbc62773f9d3842..eb810282e20ca65940e2e1a68dbaf8d72806289f 100644 (file)
@@ -1,6 +1,6 @@
 from os import path
 
-__version__ = '0.4.3'
+__version__ = '0.5.0'
 
 package_dir = path.abspath(path.dirname(__file__))
 
index 4dff7bafbc727960706c64e71f61a5230d322879..f5640c5b38e56ed85d6b946c61be3e9aa7115b95 100644 (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_]
index bf2c89d10605540625eb39367ee31836cd53d428..6d7caf087f57be72e22e91e7374d62fdeab1185e 100644 (file)
@@ -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
+
+
+
index 9f8dd2491b464d0afb25293625f51000ef81f900..8e52544f5fb2fbd8bcd49af96fd785685cac00bf 100644 (file)
@@ -4,15 +4,31 @@ Changelog
 ==========
 
 .. changelog::
-    :version: 0.4.3
+    :version: 0.5.0
 
     .. change::
-        :tags: bug, documentation
+        :tags: bug
+        :tickets: 104
+
+      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.
 
-      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.
+        :meth:`.Operations.drop_constraint` - ``type`` -> ``type_`` - old
+        name will work for backwards compatibility
 
 .. changelog::
     :version: 0.4.2
index 280003cae639cf8c36260fe57d95995da44a5552..4113e333ad9a205868044e4854e3676696ad5040 100644 (file)
@@ -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",
index 456aab7ccb0844bdc11ba9d6d189a0014b1a0696..5048376657c0541d648aa56a8d13983863c7c252 100644 (file)
@@ -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 "
     )
index 6feb7eecf19c7bdf485703377bb73f8bc2ac7bdc..438a54763b69fe72c70df65c7463782cf8bee53a 100644 (file)
@@ -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"
+    )
+