summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--migrate/changeset/__init__.py3
-rw-r--r--migrate/changeset/databases/ibmdb2.py13
-rw-r--r--migrate/tests/versioning/test_cfgparse.py2
-rw-r--r--migrate/tests/versioning/test_repository.py2
-rw-r--r--migrate/tests/versioning/test_script.py22
-rw-r--r--migrate/tests/versioning/test_shell.py3
-rw-r--r--migrate/versioning/script/sql.py19
-rw-r--r--migrate/versioning/templates/manage/default.py_tmpl1
-rw-r--r--migrate/versioning/templates/manage/pylons.py_tmpl1
-rw-r--r--setup.cfg3
-rw-r--r--tox.ini52
11 files changed, 101 insertions, 20 deletions
diff --git a/migrate/changeset/__init__.py b/migrate/changeset/__init__.py
index 256d704..7eb256a 100644
--- a/migrate/changeset/__init__.py
+++ b/migrate/changeset/__init__.py
@@ -5,13 +5,10 @@
.. [#] SQL Data Definition Language
"""
import re
-import warnings
import sqlalchemy
from sqlalchemy import __version__ as _sa_version
-warnings.simplefilter('always', DeprecationWarning)
-
_sa_version = tuple(int(re.match("\d+", x).group(0)) for x in _sa_version.split("."))
SQLA_07 = _sa_version >= (0, 7)
SQLA_08 = _sa_version >= (0, 8)
diff --git a/migrate/changeset/databases/ibmdb2.py b/migrate/changeset/databases/ibmdb2.py
index fe28512..7b6a3a1 100644
--- a/migrate/changeset/databases/ibmdb2.py
+++ b/migrate/changeset/databases/ibmdb2.py
@@ -14,6 +14,7 @@ from sqlalchemy.schema import (Index,
from migrate.changeset import ansisql
from migrate.changeset import constraint
+from migrate.changeset import util
from migrate import exceptions
@@ -107,7 +108,8 @@ class IBMDBSchemaChanger(IBMDBSchemaGenerator, ansisql.ANSISchemaChanger):
"""Rename a table; #38. Other ops aren't supported."""
self._rename_table(table)
- self.append("TO %s" % self.preparer.quote(table.new_name, table.quote))
+ q = util.safe_quote(table)
+ self.append("TO %s" % self.preparer.quote(table.new_name, q))
self.execute()
self.append("COMMIT")
self.execute()
@@ -128,10 +130,11 @@ class IBMDBSchemaChanger(IBMDBSchemaGenerator, ansisql.ANSISchemaChanger):
def _run_subvisit(self, delta, func, start_alter=True):
"""Runs visit method based on what needs to be changed on column"""
table = delta.table
+ q = util.safe_quote(table)
if start_alter:
self.start_alter_table(table)
ret = func(table,
- self.preparer.quote(delta.current_name, delta.quote),
+ self.preparer.quote(delta.current_name, q),
delta)
self.execute()
self._reorg_table(self.preparer.format_table(delta.table))
@@ -262,13 +265,13 @@ class IBMDBConstraintGenerator(ansisql.ANSIConstraintGenerator):
if (isinstance(constraint, UniqueConstraint) and
is_unique_constraint_with_null_columns_supported(
self.dialect)):
- for column in constraint.columns._all_cols:
+ for column in constraint:
if column.nullable:
constraint.exclude_nulls = True
break
if getattr(constraint, 'exclude_nulls', None):
index = Index(constraint.name,
- *(column for column in constraint.columns._all_cols),
+ *(column for column in constraint),
unique=True)
sql = self.process(CreateIndex(index))
sql += ' EXCLUDE NULL KEYS'
@@ -285,7 +288,7 @@ class IBMDBConstraintDropper(ansisql.ANSIConstraintDropper,
if (isinstance(constraint, UniqueConstraint) and
is_unique_constraint_with_null_columns_supported(
self.dialect)):
- for column in constraint.columns._all_cols:
+ for column in constraint:
if column.nullable:
constraint.exclude_nulls = True
break
diff --git a/migrate/tests/versioning/test_cfgparse.py b/migrate/tests/versioning/test_cfgparse.py
index 39649cc..a31273e 100644
--- a/migrate/tests/versioning/test_cfgparse.py
+++ b/migrate/tests/versioning/test_cfgparse.py
@@ -24,4 +24,4 @@ class TestConfigParser(fixture.Base):
'repository_name', {})
specified_text = Repository.prepare_config(Template().get_repository(),
'repository_name', {'version_table': '_other_table'})
- self.assertNotEquals(default_text, specified_text)
+ self.assertNotEqual(default_text, specified_text)
diff --git a/migrate/tests/versioning/test_repository.py b/migrate/tests/versioning/test_repository.py
index 6845a0e..6e87c02 100644
--- a/migrate/tests/versioning/test_repository.py
+++ b/migrate/tests/versioning/test_repository.py
@@ -44,7 +44,7 @@ class TestRepository(fixture.Pathed):
self.assertTrue(repos.config.get('db_settings', 'version_table'))
# version_table's default isn't none
- self.assertNotEquals(repos.config.get('db_settings', 'version_table'), 'None')
+ self.assertNotEqual(repos.config.get('db_settings', 'version_table'), 'None')
def test_load_notfound(self):
"""Nonexistant repositories shouldn't be loaded"""
diff --git a/migrate/tests/versioning/test_script.py b/migrate/tests/versioning/test_script.py
index c26b03b..954bc0d 100644
--- a/migrate/tests/versioning/test_script.py
+++ b/migrate/tests/versioning/test_script.py
@@ -271,3 +271,25 @@ class TestSqlScript(fixture.Pathed, fixture.DB):
sqls = SqlScript(src)
sqls.run(self.engine)
tmp_sql_table.metadata.drop_all(self.engine, checkfirst=True)
+
+ @fixture.usedb()
+ def test_transaction_management_statements(self):
+ """
+ Test that we can successfully execute SQL scripts with transaction
+ management statements.
+ """
+ for script_pattern in (
+ "BEGIN TRANSACTION; %s; COMMIT;",
+ "BEGIN; %s; END TRANSACTION;",
+ ):
+
+ test_statement = ("CREATE TABLE TEST1 (field1 int); "
+ "DROP TABLE TEST1")
+ script = script_pattern % test_statement
+ src = self.tmp()
+
+ with open(src, 'wt') as f:
+ f.write(script)
+
+ sqls = SqlScript(src)
+ sqls.run(self.engine)
diff --git a/migrate/tests/versioning/test_shell.py b/migrate/tests/versioning/test_shell.py
index 62dc8e0..173e30e 100644
--- a/migrate/tests/versioning/test_shell.py
+++ b/migrate/tests/versioning/test_shell.py
@@ -101,7 +101,7 @@ class TestShellCommands(Shell):
# The default table should not be None
repos_ = Repository(repos)
- self.assertNotEquals(repos_.config.get('db_settings', 'version_table'), 'None')
+ self.assertNotEqual(repos_.config.get('db_settings', 'version_table'), 'None')
# Can't create it again: it already exists
result = self.env.run('migrate create %s repository_name' % repos,
@@ -485,7 +485,6 @@ class TestShellDatabase(Shell, DB):
result = self.env.run('migrate compare_model_to_db %s %s --model=%s' \
% (self.url, repos_path, model_module.replace(":", ".")), expect_error=True)
self.assertEqual(result.returncode, 0)
- self.assertTrue("DeprecationWarning" in result.stderr)
self.assertTrue("tables missing from database: tmp_account_rundiffs" in result.stdout)
# Update db to latest model.
diff --git a/migrate/versioning/script/sql.py b/migrate/versioning/script/sql.py
index 70b49ec..4b0536d 100644
--- a/migrate/versioning/script/sql.py
+++ b/migrate/versioning/script/sql.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
+import re
import shutil
import sqlparse
@@ -36,13 +37,29 @@ class SqlScript(base.BaseScript):
try:
trans = conn.begin()
try:
+ # ignore transaction management statements that are
+ # redundant in SQL script context and result in
+ # operational error being returned.
+ #
+ # Note: we don't ignore ROLLBACK in migration scripts
+ # since its usage would be insane anyway, and we're
+ # better to fail on its occurance instead of ignoring it
+ # (and committing transaction, which is contradictory to
+ # the whole idea of ROLLBACK)
+ ignored_statements = ('BEGIN', 'END', 'COMMIT')
+ ignored_regex = re.compile('^\s*(%s).*;?$' % '|'.join(ignored_statements),
+ re.IGNORECASE)
+
# NOTE(ihrachys): script may contain multiple statements, and
# not all drivers reliably handle multistatement queries or
# commands passed to .execute(), so split them and execute one
# by one
for statement in sqlparse.split(text):
if statement:
- conn.execute(statement)
+ if re.match(ignored_regex, statement):
+ log.warning('"%s" found in SQL script; ignoring' % statement)
+ else:
+ conn.execute(statement)
trans.commit()
except Exception as e:
log.error("SQL script %s failed: %s", self.path, e)
diff --git a/migrate/versioning/templates/manage/default.py_tmpl b/migrate/versioning/templates/manage/default.py_tmpl
index e72097a..971c70f 100644
--- a/migrate/versioning/templates/manage/default.py_tmpl
+++ b/migrate/versioning/templates/manage/default.py_tmpl
@@ -5,6 +5,7 @@ from migrate.versioning.shell import main
import six
_vars = locals().copy()
del _vars['__template_name__']
+del _vars['six']
_vars.pop('repository_name', None)
defaults = ", ".join(["%s='%s'" % var for var in six.iteritems(_vars)])
}}
diff --git a/migrate/versioning/templates/manage/pylons.py_tmpl b/migrate/versioning/templates/manage/pylons.py_tmpl
index ccaac05..0d6c32c 100644
--- a/migrate/versioning/templates/manage/pylons.py_tmpl
+++ b/migrate/versioning/templates/manage/pylons.py_tmpl
@@ -20,6 +20,7 @@ else:
import six
_vars = locals().copy()
del _vars['__template_name__']
+del _vars['six']
defaults = ", ".join(["%s='%s'" % var for var in six.iteritems(_vars)])
}}
diff --git a/setup.cfg b/setup.cfg
index 2d16c95..8ab1d6c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -30,6 +30,3 @@ console_scripts =
all_files = 1
build-dir = doc/build
source-dir = doc/source
-
-[egg_info]
-tag_svn_revision = 1
diff --git a/tox.ini b/tox.ini
index 7288937..f272695 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,7 @@
[tox]
minversion = 1.6
skipsdist = True
-envlist = py26,py27,py26sa07,py27sa07,py26sa08,py27sa08,py26sa09,py27sa09,py33,pep8
+envlist = py26,py27,py26sa07,py27sa07,py26sa08,py27sa08,py26sa09,py27sa09,py33,py34,pep8
[testenv]
usedevelop = True
@@ -63,6 +63,11 @@ deps = sqlalchemy>=0.9
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/test-requirements-py3.txt
+[testenv:py34]
+deps = sqlalchemy>=0.9
+ -r{toxinidir}/test-requirements.txt
+ -r{toxinidir}/test-requirements-py3.txt
+
[testenv:pep8]
commands = flake8
@@ -75,12 +80,51 @@ commands =
python setup.py testr --slowest --testr-args='{posargs}'
[flake8]
-# F841 local variable 'json_template' is assigned to but never used
+# E121 continuation line indentation is not a multiple of four
+# E122 continuation line missing indentation or outdented
+# E123 closing bracket does not match indentation of opening bracket's line
+# E124 closing bracket does not match visual indentation
+# E125 continuation line does not distinguish itself from next logical line
+# E126 continuation line over-indented for hanging indent
+# E127 continuation line over-indented for visual indent
+# E128 continuation line under-indented for visual indent
+# E202 whitespace before ')'
+# E203 whitespace before ','
+# E225 missing whitespace around operator
+# E226 missing whitespace around arithmetic operator
+# E228 missing whitespace around modulo operator
+# E231 missing whitespace after ','
+# H234 assertEquals is deprecated, use assertEqual
+# E251 unexpected spaces around keyword / parameter equals
+# E261 at least two spaces before inline comment
+# E272 multiple spaces before keyword
+# E301 expected 1 blank line, found 0
+# E302 expected 2 blank lines, found 1
+# E303 too many blank lines (3)
+# E401 multiple imports on one line
+# E501 line too long (<number-of-chars> > 79 characters)
+# E502 the backslash is redundant between brackets
+# E702 multiple statements on one line (semicolon)
+# E712 comparison to True should be 'if cond is True:' or 'if cond:'
+# F401 '<module>' imported but unused
+# F403 'from migrate.exceptions import *' used; unable to detect undefined names
+# F811 redefinition of unused '<type>' from line <lineno>
+# F821 undefined name '<name>'
+# F841 local variable '<variable>' is assigned to but never used
+# H101 Use TODO(NAME)
# H201 no 'except:' at least use 'except Exception:'
-# H302 import only modules.'bla..' does not import a module
+# H202 assertRaises Exception too broad
+# H233 Python 3.x incompatible use of print operator
+# H301 one import per line
+# H302 import only modules. '<import>' does not import a module
# H306 imports not in alphabetical order
+# H401 docstring should not start with a space
+# H402 one line docstring needs punctuation.
+# H403 multi line docstring end on new line
# H404 multi line docstring should start with a summary
-ignore = F841,H201,H302,H306,H404
+# H501 Do not use locals() for string formatting
+# W391 blank line at end of file
+ignore = E121,E122,E123,E124,E125,E126,E127,E128,E202,E203,E225,E226,E228,E231,E251,E261,E272,E301,E302,E303,E401,E501,E502,E702,E712,F401,F403,F811,F821,F841,H101,H201,H202,H233,H234,H301,H302,H306,H401,H402,H403,H404,H501,W391
show-source = true
builtins = _
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,tools,build