Hello community, here is the log from the commit of package python-sqlalchemy-migrate for openSUSE:Factory checked in at 2014-09-17 17:26:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-sqlalchemy-migrate (Old) and /work/SRC/openSUSE:Factory/.python-sqlalchemy-migrate.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-sqlalchemy-migrate" Changes: -------- --- /work/SRC/openSUSE:Factory/python-sqlalchemy-migrate/python-sqlalchemy-migrate.changes 2014-05-24 07:41:13.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-sqlalchemy-migrate.new/python-sqlalchemy-migrate.changes 2014-09-17 17:27:28.000000000 +0200 @@ -1,0 +2,9 @@ +Tue Sep 16 06:26:48 UTC 2014 - tbecht...@suse.com + +- update to version 0.9.2: + * SqlScript: execute multiple statements one by one + * Make sure we don't throw away exception on SQL script failure + * Pin testtools to < 0.9.36 +- update Requires according to requirements.txt + +------------------------------------------------------------------- Old: ---- sqlalchemy-migrate-0.9.1.tar.gz New: ---- sqlalchemy-migrate-0.9.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-sqlalchemy-migrate.spec ++++++ --- /var/tmp/diff_new_pack.ezMeho/_old 2014-09-17 17:27:29.000000000 +0200 +++ /var/tmp/diff_new_pack.ezMeho/_new 2014-09-17 17:27:29.000000000 +0200 @@ -18,7 +18,7 @@ Name: python-sqlalchemy-migrate -Version: 0.9.1 +Version: 0.9.2 Release: 0 Summary: Database schema migration for SQLAlchemy License: MIT @@ -36,9 +36,12 @@ BuildRequires: python-decorator #BuildRequires: python-pysqlite #BuildRequires: python-pytz -Requires: python-SQLAlchemy >= 0.6 +Requires: python-SQLAlchemy >= 0.7.8 +Requires: python-Tempita >= 0.4 Requires: python-Tempita >= 0.4 Requires: python-decorator +Requires: python-six >= 1.4.1 +Requires: python-sqlparse BuildRoot: %{_tmppath}/%{name}-%{version}-build %if 0%{?suse_version} && 0%{?suse_version} <= 1110 %{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} ++++++ sqlalchemy-migrate-0.9.1.tar.gz -> sqlalchemy-migrate-0.9.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/AUTHORS new/sqlalchemy-migrate-0.9.2/AUTHORS --- old/sqlalchemy-migrate-0.9.1/AUTHORS 2014-05-06 16:40:25.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/AUTHORS 2014-09-11 18:42:29.000000000 +0200 @@ -1,5 +1,43 @@ - +Alex Favaro <alexfav...@gmail.com> +Bob Farrell <robertanthonyfarr...@gmail.com> +Chris Withers <ch...@simplistix.co.uk> +Cyril Roelandt <cyril.roela...@enovance.com> +Dan Prince <dpri...@redhat.com> +David Ripton <drip...@redhat.com> +Domen Kožar <do...@dev.si> +Dustin J. Mitchell <dus...@mozilla.com> +Eric Harney <ehar...@redhat.com> +Gabriel <g2p.code+s...@gmail.com> +Ihar Hrachyshka <ihrac...@redhat.com> +Jan Dittberner <jan.dittber...@gmail.com> +Jan Dittberner <jan.dittber...@googlemail.com> +Jan Dittberner <j...@dittberner.info> +Jason Michalski <arm...@armooo.net> +Josip Delic <delij...@googlemail.com> +Matt Riedemann <mrie...@us.ibm.com> +Monty Taylor <mord...@inaugust.com> +Pete Keen <p...@bugsplat.info> +Pádraig Brady <p...@draigbrady.com> Pádraig Brady <pbr...@redhat.com> Rahul Priyadarshi <rahul.priyadar...@in.ibm.com> +Rick Copeland <rick...@usa.net> +Roman Podolyaka <rpodoly...@mirantis.com> +Sascha Peilicke <sasc...@gmx.de> +Sascha Peilicke <speili...@suse.com> +Sean Dague <sean.da...@samsung.com> Sheng Bo Hou <sb...@cn.ibm.com> +Thomas Goirand <tho...@goirand.fr> Thuy Christenson <t...@us.ibm.com> +al.ya...@gmail.com <unknown> +asuffi...@gmail.com <unknown> +ches.martin <unknown> +christian.simms <unknown> +chrisw <unknown> +emil.kroymann <unknown> +hud...@fubarite.fubar.si <unknown> +iElectric <unknown> +jan.dittberner <unknown> +mark...@gmail.com <unknown> +percious17 <unknown> +r...@fubarite.fubar.si <unknown> +wyue...@gmail.com <unknown> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/ChangeLog new/sqlalchemy-migrate-0.9.2/ChangeLog --- old/sqlalchemy-migrate-0.9.1/ChangeLog 2014-05-06 16:40:25.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/ChangeLog 2014-09-11 18:42:29.000000000 +0200 @@ -1,6 +1,13 @@ CHANGES ======= +0.9.2 +----- + +* SqlScript: execute multiple statements one by one +* Make sure we don't throw away exception on SQL script failure +* Pin testtools to < 0.9.36 + 0.9.1 ----- @@ -19,6 +26,7 @@ * Conditionally import ibmdb2/ibm_db_sa * migrate needs subunit >= 0.0.18 * UniqueConstraint named and escaped twice +* Fix 3 files with Windows line endings to Unix line endings * Eradicate trailing whitespace * Convert tabs to spaces in a couple of rst files diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/PKG-INFO new/sqlalchemy-migrate-0.9.2/PKG-INFO --- old/sqlalchemy-migrate-0.9.1/PKG-INFO 2014-05-06 16:40:25.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/PKG-INFO 2014-09-11 18:42:29.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: sqlalchemy-migrate -Version: 0.9.1 +Version: 0.9.2 Summary: Database schema migration for SQLAlchemy Home-page: http://www.openstack.org/ Author: OpenStack diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/doc/source/theme/layout.html new/sqlalchemy-migrate-0.9.2/doc/source/theme/layout.html --- old/sqlalchemy-migrate-0.9.1/doc/source/theme/layout.html 2014-05-06 16:39:34.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/doc/source/theme/layout.html 2014-09-11 18:41:48.000000000 +0200 @@ -1,90 +1,90 @@ -<?xml version="1.0"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - -<?python -import pudge - -def initialize(t): - g = t.generator - if not hasattr(t, 'title'): - t.title = 'Untitled' - t.doc_title = g.index_document['title'] - t.home_url = g.organization_url or g.blog_url or g.trac_url - t.home_title = g.organization -?> - -<html xmlns="http://www.w3.org/1999/xhtml" - xmlns:py="http://purl.org/kid/ns#" - py:def="layout"> - - <head> - <title>${title}</title> - <link rel="stylesheet" type="text/css" href="layout.css"/> - <link py:if="generator.syndication_url" - rel="alternate" - type="application/rss+xml" - title="RSS 2.0" href="${generator.syndication_url}"/> - - </head> - <body> - <div id="page"> - <h1 class="doc-title"><a href="${home_url}">${home_title}</a></h1> - <div id="navcontainer"> - <ul id="navlist"> - <li class="pagenav"> - <ul> - <li class="page_item"> - <a href="index.html" - class="${'index.html'== destfile and 'selected' or ''}" - title="Project Home / Index">${doc_title}</a> - </li> - <li class="page_item"> - <a href="module-index.html" - class="${'module-index.html'== destfile and 'selected' or ''}" - title="${doc_title.lower()} package and module reference">Modules</a> - </li> - <?python - trac_url = generator.trac_url - mailing_list_url = generator.mailing_list_url - ?> - <li py:if="trac_url"> - <a href="${trac_url}" - title="Wiki / Subversion / Roadmap / Bug Tracker" - >Trac</a> - </li> - <li py:if="generator.blog_url"> - <a href="${generator.blog_url}">Blog</a> - </li> - <li py:if="mailing_list_url"> - <a href="${mailing_list_url}" - class="${mailing_list_url == destfile and 'selected' or ''}" - title="Mailing List">Discuss</a> - </li> - </ul> - </li> - </ul> - </div> - - <hr /> - - <div id="content" py:content="content()"/> - - <div id="footer"> - <?python license = generator.get_document('doc-license') ?> - - <p style="float: left;"> - built with - <a href="http://lesscode.org/projects/pudge/" - >pudge/${pudge.__version__}</a><br /> - original design by - <a href="http://blog.ratterobert.com/" - >ratter / robert</a><br /> - </p> - <p style="float:right;"> - evan.rosson (at) gmail.com - </p> - </div> - </div> - </body> - -</html> +<?xml version="1.0"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<?python +import pudge + +def initialize(t): + g = t.generator + if not hasattr(t, 'title'): + t.title = 'Untitled' + t.doc_title = g.index_document['title'] + t.home_url = g.organization_url or g.blog_url or g.trac_url + t.home_title = g.organization +?> + +<html xmlns="http://www.w3.org/1999/xhtml" + xmlns:py="http://purl.org/kid/ns#" + py:def="layout"> + + <head> + <title>${title}</title> + <link rel="stylesheet" type="text/css" href="layout.css"/> + <link py:if="generator.syndication_url" + rel="alternate" + type="application/rss+xml" + title="RSS 2.0" href="${generator.syndication_url}"/> + + </head> + <body> + <div id="page"> + <h1 class="doc-title"><a href="${home_url}">${home_title}</a></h1> + <div id="navcontainer"> + <ul id="navlist"> + <li class="pagenav"> + <ul> + <li class="page_item"> + <a href="index.html" + class="${'index.html'== destfile and 'selected' or ''}" + title="Project Home / Index">${doc_title}</a> + </li> + <li class="page_item"> + <a href="module-index.html" + class="${'module-index.html'== destfile and 'selected' or ''}" + title="${doc_title.lower()} package and module reference">Modules</a> + </li> + <?python + trac_url = generator.trac_url + mailing_list_url = generator.mailing_list_url + ?> + <li py:if="trac_url"> + <a href="${trac_url}" + title="Wiki / Subversion / Roadmap / Bug Tracker" + >Trac</a> + </li> + <li py:if="generator.blog_url"> + <a href="${generator.blog_url}">Blog</a> + </li> + <li py:if="mailing_list_url"> + <a href="${mailing_list_url}" + class="${mailing_list_url == destfile and 'selected' or ''}" + title="Mailing List">Discuss</a> + </li> + </ul> + </li> + </ul> + </div> + + <hr /> + + <div id="content" py:content="content()"/> + + <div id="footer"> + <?python license = generator.get_document('doc-license') ?> + + <p style="float: left;"> + built with + <a href="http://lesscode.org/projects/pudge/" + >pudge/${pudge.__version__}</a><br /> + original design by + <a href="http://blog.ratterobert.com/" + >ratter / robert</a><br /> + </p> + <p style="float:right;"> + evan.rosson (at) gmail.com + </p> + </div> + </div> + </body> + +</html> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/migrate/changeset/databases/ibmdb2.py new/sqlalchemy-migrate-0.9.2/migrate/changeset/databases/ibmdb2.py --- old/sqlalchemy-migrate-0.9.1/migrate/changeset/databases/ibmdb2.py 2014-05-06 16:39:34.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/migrate/changeset/databases/ibmdb2.py 2014-09-11 18:41:48.000000000 +0200 @@ -1,313 +1,313 @@ -""" - DB2 database specific implementations of changeset classes. -""" - -import logging - -from ibm_db_sa import base -from sqlalchemy.schema import (AddConstraint, - CreateIndex, - DropConstraint) -from sqlalchemy.schema import (Index, - PrimaryKeyConstraint, - UniqueConstraint) - -from migrate.changeset import ansisql -from migrate.changeset import constraint -from migrate import exceptions - - -LOG = logging.getLogger(__name__) - -IBMDBSchemaGenerator = base.IBM_DBDDLCompiler - - -def get_server_version_info(dialect): - """Returns the DB2 server major and minor version as a list of ints.""" - return [int(ver_token) for ver_token in dialect.dbms_ver.split('.')[0:2]] - - -def is_unique_constraint_with_null_columns_supported(dialect): - """Checks to see if the DB2 version is at least 10.5. - - This is needed for checking if unique constraints with null columns - are supported. - """ - return get_server_version_info(dialect) >= [10, 5] - - -class IBMDBColumnGenerator(IBMDBSchemaGenerator, - ansisql.ANSIColumnGenerator): - def visit_column(self, column): - nullable = True - if not column.nullable: - nullable = False - column.nullable = True - - table = self.start_alter_table(column) - self.append("ADD COLUMN ") - self.append(self.get_column_specification(column)) - - for cons in column.constraints: - self.traverse_single(cons) - if column.default is not None: - self.traverse_single(column.default) - self.execute() - - #ALTER TABLE STATEMENTS - if not nullable: - self.start_alter_table(column) - self.append("ALTER COLUMN %s SET NOT NULL" % - self.preparer.format_column(column)) - self.execute() - self.append("CALL SYSPROC.ADMIN_CMD('REORG TABLE %s')" % - self.preparer.format_table(table)) - self.execute() - - # add indexes and unique constraints - if column.index_name: - Index(column.index_name, column).create() - elif column.unique_name: - constraint.UniqueConstraint(column, - name=column.unique_name).create() - - # SA bounds FK constraints to table, add manually - for fk in column.foreign_keys: - self.add_foreignkey(fk.constraint) - - # add primary key constraint if needed - if column.primary_key_name: - pk = constraint.PrimaryKeyConstraint( - column, name=column.primary_key_name) - pk.create() - - self.append("COMMIT") - self.execute() - self.append("CALL SYSPROC.ADMIN_CMD('REORG TABLE %s')" % - self.preparer.format_table(table)) - self.execute() - - -class IBMDBColumnDropper(ansisql.ANSIColumnDropper): - def visit_column(self, column): - """Drop a column from its table. - - :param column: the column object - :type column: :class:`sqlalchemy.Column` - """ - #table = self.start_alter_table(column) - super(IBMDBColumnDropper, self).visit_column(column) - self.append("CALL SYSPROC.ADMIN_CMD('REORG TABLE %s')" % - self.preparer.format_table(column.table)) - self.execute() - - -class IBMDBSchemaChanger(IBMDBSchemaGenerator, ansisql.ANSISchemaChanger): - def visit_table(self, table): - """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)) - self.execute() - self.append("COMMIT") - self.execute() - - def _rename_table(self, table): - self.append("RENAME TABLE %s " % self.preparer.format_table(table)) - - def visit_index(self, index): - old_name = self.preparer.quote(self._index_identifier(index.name), - index.quote) - new_name = self.preparer.quote(self._index_identifier(index.new_name), - index.quote) - self.append("RENAME INDEX %s TO %s" % (old_name, new_name)) - self.execute() - self.append("COMMIT") - self.execute() - - def _run_subvisit(self, delta, func, start_alter=True): - """Runs visit method based on what needs to be changed on column""" - table = delta.table - if start_alter: - self.start_alter_table(table) - ret = func(table, - self.preparer.quote(delta.current_name, delta.quote), - delta) - self.execute() - self._reorg_table(self.preparer.format_table(delta.table)) - - def _reorg_table(self, delta): - self.append("CALL SYSPROC.ADMIN_CMD('REORG TABLE %s')" % delta) - self.execute() - - def visit_column(self, delta): - keys = delta.keys() - tr = self.connection.begin() - column = delta.result_column.copy() - - if 'type' in keys: - try: - self._run_subvisit(delta, self._visit_column_change, False) - except Exception as e: - LOG.warn("Unable to change the column type. Error: %s" % e) - - if column.primary_key and 'primary_key' not in keys: - try: - self._run_subvisit(delta, self._visit_primary_key) - except Exception as e: - LOG.warn("Unable to add primary key. Error: %s" % e) - - if 'nullable' in keys: - self._run_subvisit(delta, self._visit_column_nullable) - - if 'server_default' in keys: - self._run_subvisit(delta, self._visit_column_default) - - if 'primary_key' in keys: - self._run_subvisit(delta, self._visit_primary_key) - self._run_subvisit(delta, self._visit_unique_constraint) - - if 'name' in keys: - try: - self._run_subvisit(delta, self._visit_column_name, False) - except Exception as e: - LOG.warn("Unable to change column %(name)s. Error: %(error)s" % - {'name': delta.current_name, 'error': e}) - - self._reorg_table(self.preparer.format_table(delta.table)) - self.append("COMMIT") - self.execute() - tr.commit() - - def _visit_unique_constraint(self, table, col_name, delta): - # Add primary key to the current column - self.append("ADD CONSTRAINT %s " % col_name) - self.append("UNIQUE (%s)" % col_name) - - def _visit_primary_key(self, table, col_name, delta): - # Add primary key to the current column - self.append("ADD PRIMARY KEY (%s)" % col_name) - - def _visit_column_name(self, table, col_name, delta): - column = delta.result_column.copy() - - # Delete the primary key before renaming the column - if column.primary_key: - try: - self.start_alter_table(table) - self.append("DROP PRIMARY KEY") - self.execute() - except Exception: - LOG.debug("Continue since Primary key does not exist.") - - self.start_alter_table(table) - new_name = self.preparer.format_column(delta.result_column) - self.append("RENAME COLUMN %s TO %s" % (col_name, new_name)) - - if column.primary_key: - # execute the rename before adding primary key back - self.execute() - self.start_alter_table(table) - self.append("ADD PRIMARY KEY (%s)" % new_name) - - def _visit_column_nullable(self, table, col_name, delta): - self.append("ALTER COLUMN %s " % col_name) - nullable = delta['nullable'] - if nullable: - self.append("DROP NOT NULL") - else: - self.append("SET NOT NULL") - - def _visit_column_default(self, table, col_name, delta): - default_text = self.get_column_default_string(delta.result_column) - self.append("ALTER COLUMN %s " % col_name) - if default_text is None: - self.append("DROP DEFAULT") - else: - self.append("SET WITH DEFAULT %s" % default_text) - - def _visit_column_change(self, table, col_name, delta): - column = delta.result_column.copy() - - # Delete the primary key before - if column.primary_key: - try: - self.start_alter_table(table) - self.append("DROP PRIMARY KEY") - self.execute() - except Exception: - LOG.debug("Continue since Primary key does not exist.") - # Delete the identity before - try: - self.start_alter_table(table) - self.append("ALTER COLUMN %s DROP IDENTITY" % col_name) - self.execute() - except Exception: - LOG.debug("Continue since identity does not exist.") - - column.default = None - if not column.table: - column.table = delta.table - self.start_alter_table(table) - self.append("ALTER COLUMN %s " % col_name) - self.append("SET DATA TYPE ") - type_text = self.dialect.type_compiler.process( - delta.result_column.type) - self.append(type_text) - - -class IBMDBConstraintGenerator(ansisql.ANSIConstraintGenerator): - def _visit_constraint(self, constraint): - constraint.name = self.get_constraint_name(constraint) - if (isinstance(constraint, UniqueConstraint) and - is_unique_constraint_with_null_columns_supported( - self.dialect)): - for column in constraint.columns._all_cols: - 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), - unique=True) - sql = self.process(CreateIndex(index)) - sql += ' EXCLUDE NULL KEYS' - else: - sql = self.process(AddConstraint(constraint)) - self.append(sql) - self.execute() - - -class IBMDBConstraintDropper(ansisql.ANSIConstraintDropper, - ansisql.ANSIConstraintCommon): - def _visit_constraint(self, constraint): - constraint.name = self.get_constraint_name(constraint) - if (isinstance(constraint, UniqueConstraint) and - is_unique_constraint_with_null_columns_supported( - self.dialect)): - for column in constraint.columns._all_cols: - if column.nullable: - constraint.exclude_nulls = True - break - if getattr(constraint, 'exclude_nulls', None): - index_name = self.preparer.quote( - self._index_identifier(constraint.name), constraint.quote) - sql = 'DROP INDEX %s ' % index_name - else: - sql = self.process(DropConstraint(constraint, - cascade=constraint.cascade)) - self.append(sql) - self.execute() - - def visit_migrate_primary_key_constraint(self, constraint): - self.start_alter_table(constraint.table) - self.append("DROP PRIMARY KEY") - self.execute() - - -class IBMDBDialect(ansisql.ANSIDialect): - columngenerator = IBMDBColumnGenerator - columndropper = IBMDBColumnDropper - schemachanger = IBMDBSchemaChanger - constraintgenerator = IBMDBConstraintGenerator - constraintdropper = IBMDBConstraintDropper +""" + DB2 database specific implementations of changeset classes. +""" + +import logging + +from ibm_db_sa import base +from sqlalchemy.schema import (AddConstraint, + CreateIndex, + DropConstraint) +from sqlalchemy.schema import (Index, + PrimaryKeyConstraint, + UniqueConstraint) + +from migrate.changeset import ansisql +from migrate.changeset import constraint +from migrate import exceptions + + +LOG = logging.getLogger(__name__) + +IBMDBSchemaGenerator = base.IBM_DBDDLCompiler + + +def get_server_version_info(dialect): + """Returns the DB2 server major and minor version as a list of ints.""" + return [int(ver_token) for ver_token in dialect.dbms_ver.split('.')[0:2]] + + +def is_unique_constraint_with_null_columns_supported(dialect): + """Checks to see if the DB2 version is at least 10.5. + + This is needed for checking if unique constraints with null columns + are supported. + """ + return get_server_version_info(dialect) >= [10, 5] + + +class IBMDBColumnGenerator(IBMDBSchemaGenerator, + ansisql.ANSIColumnGenerator): + def visit_column(self, column): + nullable = True + if not column.nullable: + nullable = False + column.nullable = True + + table = self.start_alter_table(column) + self.append("ADD COLUMN ") + self.append(self.get_column_specification(column)) + + for cons in column.constraints: + self.traverse_single(cons) + if column.default is not None: + self.traverse_single(column.default) + self.execute() + + #ALTER TABLE STATEMENTS + if not nullable: + self.start_alter_table(column) + self.append("ALTER COLUMN %s SET NOT NULL" % + self.preparer.format_column(column)) + self.execute() + self.append("CALL SYSPROC.ADMIN_CMD('REORG TABLE %s')" % + self.preparer.format_table(table)) + self.execute() + + # add indexes and unique constraints + if column.index_name: + Index(column.index_name, column).create() + elif column.unique_name: + constraint.UniqueConstraint(column, + name=column.unique_name).create() + + # SA bounds FK constraints to table, add manually + for fk in column.foreign_keys: + self.add_foreignkey(fk.constraint) + + # add primary key constraint if needed + if column.primary_key_name: + pk = constraint.PrimaryKeyConstraint( + column, name=column.primary_key_name) + pk.create() + + self.append("COMMIT") + self.execute() + self.append("CALL SYSPROC.ADMIN_CMD('REORG TABLE %s')" % + self.preparer.format_table(table)) + self.execute() + + +class IBMDBColumnDropper(ansisql.ANSIColumnDropper): + def visit_column(self, column): + """Drop a column from its table. + + :param column: the column object + :type column: :class:`sqlalchemy.Column` + """ + #table = self.start_alter_table(column) + super(IBMDBColumnDropper, self).visit_column(column) + self.append("CALL SYSPROC.ADMIN_CMD('REORG TABLE %s')" % + self.preparer.format_table(column.table)) + self.execute() + + +class IBMDBSchemaChanger(IBMDBSchemaGenerator, ansisql.ANSISchemaChanger): + def visit_table(self, table): + """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)) + self.execute() + self.append("COMMIT") + self.execute() + + def _rename_table(self, table): + self.append("RENAME TABLE %s " % self.preparer.format_table(table)) + + def visit_index(self, index): + old_name = self.preparer.quote(self._index_identifier(index.name), + index.quote) + new_name = self.preparer.quote(self._index_identifier(index.new_name), + index.quote) + self.append("RENAME INDEX %s TO %s" % (old_name, new_name)) + self.execute() + self.append("COMMIT") + self.execute() + + def _run_subvisit(self, delta, func, start_alter=True): + """Runs visit method based on what needs to be changed on column""" + table = delta.table + if start_alter: + self.start_alter_table(table) + ret = func(table, + self.preparer.quote(delta.current_name, delta.quote), + delta) + self.execute() + self._reorg_table(self.preparer.format_table(delta.table)) + + def _reorg_table(self, delta): + self.append("CALL SYSPROC.ADMIN_CMD('REORG TABLE %s')" % delta) + self.execute() + + def visit_column(self, delta): + keys = delta.keys() + tr = self.connection.begin() + column = delta.result_column.copy() + + if 'type' in keys: + try: + self._run_subvisit(delta, self._visit_column_change, False) + except Exception as e: + LOG.warn("Unable to change the column type. Error: %s" % e) + + if column.primary_key and 'primary_key' not in keys: + try: + self._run_subvisit(delta, self._visit_primary_key) + except Exception as e: + LOG.warn("Unable to add primary key. Error: %s" % e) + + if 'nullable' in keys: + self._run_subvisit(delta, self._visit_column_nullable) + + if 'server_default' in keys: + self._run_subvisit(delta, self._visit_column_default) + + if 'primary_key' in keys: + self._run_subvisit(delta, self._visit_primary_key) + self._run_subvisit(delta, self._visit_unique_constraint) + + if 'name' in keys: + try: + self._run_subvisit(delta, self._visit_column_name, False) + except Exception as e: + LOG.warn("Unable to change column %(name)s. Error: %(error)s" % + {'name': delta.current_name, 'error': e}) + + self._reorg_table(self.preparer.format_table(delta.table)) + self.append("COMMIT") + self.execute() + tr.commit() + + def _visit_unique_constraint(self, table, col_name, delta): + # Add primary key to the current column + self.append("ADD CONSTRAINT %s " % col_name) + self.append("UNIQUE (%s)" % col_name) + + def _visit_primary_key(self, table, col_name, delta): + # Add primary key to the current column + self.append("ADD PRIMARY KEY (%s)" % col_name) + + def _visit_column_name(self, table, col_name, delta): + column = delta.result_column.copy() + + # Delete the primary key before renaming the column + if column.primary_key: + try: + self.start_alter_table(table) + self.append("DROP PRIMARY KEY") + self.execute() + except Exception: + LOG.debug("Continue since Primary key does not exist.") + + self.start_alter_table(table) + new_name = self.preparer.format_column(delta.result_column) + self.append("RENAME COLUMN %s TO %s" % (col_name, new_name)) + + if column.primary_key: + # execute the rename before adding primary key back + self.execute() + self.start_alter_table(table) + self.append("ADD PRIMARY KEY (%s)" % new_name) + + def _visit_column_nullable(self, table, col_name, delta): + self.append("ALTER COLUMN %s " % col_name) + nullable = delta['nullable'] + if nullable: + self.append("DROP NOT NULL") + else: + self.append("SET NOT NULL") + + def _visit_column_default(self, table, col_name, delta): + default_text = self.get_column_default_string(delta.result_column) + self.append("ALTER COLUMN %s " % col_name) + if default_text is None: + self.append("DROP DEFAULT") + else: + self.append("SET WITH DEFAULT %s" % default_text) + + def _visit_column_change(self, table, col_name, delta): + column = delta.result_column.copy() + + # Delete the primary key before + if column.primary_key: + try: + self.start_alter_table(table) + self.append("DROP PRIMARY KEY") + self.execute() + except Exception: + LOG.debug("Continue since Primary key does not exist.") + # Delete the identity before + try: + self.start_alter_table(table) + self.append("ALTER COLUMN %s DROP IDENTITY" % col_name) + self.execute() + except Exception: + LOG.debug("Continue since identity does not exist.") + + column.default = None + if not column.table: + column.table = delta.table + self.start_alter_table(table) + self.append("ALTER COLUMN %s " % col_name) + self.append("SET DATA TYPE ") + type_text = self.dialect.type_compiler.process( + delta.result_column.type) + self.append(type_text) + + +class IBMDBConstraintGenerator(ansisql.ANSIConstraintGenerator): + def _visit_constraint(self, constraint): + constraint.name = self.get_constraint_name(constraint) + if (isinstance(constraint, UniqueConstraint) and + is_unique_constraint_with_null_columns_supported( + self.dialect)): + for column in constraint.columns._all_cols: + 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), + unique=True) + sql = self.process(CreateIndex(index)) + sql += ' EXCLUDE NULL KEYS' + else: + sql = self.process(AddConstraint(constraint)) + self.append(sql) + self.execute() + + +class IBMDBConstraintDropper(ansisql.ANSIConstraintDropper, + ansisql.ANSIConstraintCommon): + def _visit_constraint(self, constraint): + constraint.name = self.get_constraint_name(constraint) + if (isinstance(constraint, UniqueConstraint) and + is_unique_constraint_with_null_columns_supported( + self.dialect)): + for column in constraint.columns._all_cols: + if column.nullable: + constraint.exclude_nulls = True + break + if getattr(constraint, 'exclude_nulls', None): + index_name = self.preparer.quote( + self._index_identifier(constraint.name), constraint.quote) + sql = 'DROP INDEX %s ' % index_name + else: + sql = self.process(DropConstraint(constraint, + cascade=constraint.cascade)) + self.append(sql) + self.execute() + + def visit_migrate_primary_key_constraint(self, constraint): + self.start_alter_table(constraint.table) + self.append("DROP PRIMARY KEY") + self.execute() + + +class IBMDBDialect(ansisql.ANSIDialect): + columngenerator = IBMDBColumnGenerator + columndropper = IBMDBColumnDropper + schemachanger = IBMDBSchemaChanger + constraintgenerator = IBMDBConstraintGenerator + constraintdropper = IBMDBConstraintDropper diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/migrate/tests/fixture/warnings.py new/sqlalchemy-migrate-0.9.2/migrate/tests/fixture/warnings.py --- old/sqlalchemy-migrate-0.9.1/migrate/tests/fixture/warnings.py 2014-05-06 16:39:34.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/migrate/tests/fixture/warnings.py 2014-09-11 18:41:48.000000000 +0200 @@ -1,90 +1,88 @@ -# lifted from Python 2.6, so we can use it in Python 2.5 -import sys - -class WarningMessage(object): - - """Holds the result of a single showwarning() call.""" - - _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", - "line") - - def __init__(self, message, category, filename, lineno, file=None, - line=None): - local_values = locals() - for attr in self._WARNING_DETAILS: - setattr(self, attr, local_values[attr]) - if category: - self._category_name = category.__name__ - else: - self._category_name = None - - def __str__(self): - return ("{message : %r, category : %r, filename : %r, lineno : %s, " - "line : %r}" % (self.message, self._category_name, - self.filename, self.lineno, self.line)) - - -class catch_warnings(object): - - """A context manager that copies and restores the warnings filter upon - exiting the context. - - The 'record' argument specifies whether warnings should be captured by a - custom implementation of warnings.showwarning() and be appended to a list - returned by the context manager. Otherwise None is returned by the context - manager. The objects appended to the list are arguments whose attributes - mirror the arguments to showwarning(). - - The 'module' argument is to specify an alternative module to the module - named 'warnings' and imported under that name. This argument is only useful - when testing the warnings module itself. - - """ - - def __init__(self, record=False, module=None): - """Specify whether to record warnings and if an alternative module - should be used other than sys.modules['warnings']. - - For compatibility with Python 3.0, please consider all arguments to be - keyword-only. - - """ - self._record = record - if module is None: - self._module = sys.modules['warnings'] - else: - self._module = module - self._entered = False - - def __repr__(self): - args = [] - if self._record: - args.append("record=True") - if self._module is not sys.modules['warnings']: - args.append("module=%r" % self._module) - name = type(self).__name__ - return "%s(%s)" % (name, ", ".join(args)) - - def __enter__(self): - if self._entered: - raise RuntimeError("Cannot enter %r twice" % self) - self._entered = True - self._filters = self._module.filters - self._module.filters = self._filters[:] - self._showwarning = self._module.showwarning - if self._record: - log = [] - def showwarning(*args, **kwargs): - log.append(WarningMessage(*args, **kwargs)) - self._module.showwarning = showwarning - return log - else: - return None - - def __exit__(self, *exc_info): - if not self._entered: - raise RuntimeError("Cannot exit %r without entering first" % self) - self._module.filters = self._filters - self._module.showwarning = self._showwarning - - +# lifted from Python 2.6, so we can use it in Python 2.5 +import sys + +class WarningMessage(object): + + """Holds the result of a single showwarning() call.""" + + _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", + "line") + + def __init__(self, message, category, filename, lineno, file=None, + line=None): + local_values = locals() + for attr in self._WARNING_DETAILS: + setattr(self, attr, local_values[attr]) + if category: + self._category_name = category.__name__ + else: + self._category_name = None + + def __str__(self): + return ("{message : %r, category : %r, filename : %r, lineno : %s, " + "line : %r}" % (self.message, self._category_name, + self.filename, self.lineno, self.line)) + + +class catch_warnings(object): + + """A context manager that copies and restores the warnings filter upon + exiting the context. + + The 'record' argument specifies whether warnings should be captured by a + custom implementation of warnings.showwarning() and be appended to a list + returned by the context manager. Otherwise None is returned by the context + manager. The objects appended to the list are arguments whose attributes + mirror the arguments to showwarning(). + + The 'module' argument is to specify an alternative module to the module + named 'warnings' and imported under that name. This argument is only useful + when testing the warnings module itself. + + """ + + def __init__(self, record=False, module=None): + """Specify whether to record warnings and if an alternative module + should be used other than sys.modules['warnings']. + + For compatibility with Python 3.0, please consider all arguments to be + keyword-only. + + """ + self._record = record + if module is None: + self._module = sys.modules['warnings'] + else: + self._module = module + self._entered = False + + def __repr__(self): + args = [] + if self._record: + args.append("record=True") + if self._module is not sys.modules['warnings']: + args.append("module=%r" % self._module) + name = type(self).__name__ + return "%s(%s)" % (name, ", ".join(args)) + + def __enter__(self): + if self._entered: + raise RuntimeError("Cannot enter %r twice" % self) + self._entered = True + self._filters = self._module.filters + self._module.filters = self._filters[:] + self._showwarning = self._module.showwarning + if self._record: + log = [] + def showwarning(*args, **kwargs): + log.append(WarningMessage(*args, **kwargs)) + self._module.showwarning = showwarning + return log + else: + return None + + def __exit__(self, *exc_info): + if not self._entered: + raise RuntimeError("Cannot exit %r without entering first" % self) + self._module.filters = self._filters + self._module.showwarning = self._showwarning diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/migrate/tests/versioning/test_script.py new/sqlalchemy-migrate-0.9.2/migrate/tests/versioning/test_script.py --- old/sqlalchemy-migrate-0.9.1/migrate/tests/versioning/test_script.py 2014-05-06 16:39:34.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/migrate/tests/versioning/test_script.py 2014-09-11 18:41:49.000000000 +0200 @@ -269,5 +269,5 @@ # run the change sqls = SqlScript(src) - sqls.run(self.engine, executemany=False) + sqls.run(self.engine) tmp_sql_table.metadata.drop_all(self.engine, checkfirst=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/migrate/versioning/script/sql.py new/sqlalchemy-migrate-0.9.2/migrate/versioning/script/sql.py --- old/sqlalchemy-migrate-0.9.1/migrate/versioning/script/sql.py 2014-05-06 16:39:34.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/migrate/versioning/script/sql.py 2014-09-11 18:41:49.000000000 +0200 @@ -3,6 +3,8 @@ import logging import shutil +import sqlparse + from migrate.versioning.script import base from migrate.versioning.template import Template @@ -24,7 +26,7 @@ return cls(path) # TODO: why is step parameter even here? - def run(self, engine, step=None, executemany=True): + def run(self, engine, step=None): """Runs SQL script through raw dbapi execute call""" text = self.source() # Don't rely on SA's autocommit here @@ -34,15 +36,16 @@ try: trans = conn.begin() try: - # HACK: SQLite doesn't allow multiple statements through - # its execute() method, but it provides executescript() instead - dbapi = conn.engine.raw_connection() - if executemany and getattr(dbapi, 'executescript', None): - dbapi.executescript(text) - else: - conn.execute(text) + # 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) trans.commit() - except: + except Exception as e: + log.error("SQL script %s failed: %s", self.path, e) trans.rollback() raise finally: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/requirements.txt new/sqlalchemy-migrate-0.9.2/requirements.txt --- old/sqlalchemy-migrate-0.9.1/requirements.txt 2014-05-06 16:39:34.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/requirements.txt 2014-09-11 18:41:49.000000000 +0200 @@ -6,4 +6,5 @@ SQLAlchemy>=0.7.8 decorator six>=1.4.1 +sqlparse Tempita >= 0.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/sqlalchemy_migrate.egg-info/PKG-INFO new/sqlalchemy-migrate-0.9.2/sqlalchemy_migrate.egg-info/PKG-INFO --- old/sqlalchemy-migrate-0.9.1/sqlalchemy_migrate.egg-info/PKG-INFO 2014-05-06 16:40:25.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/sqlalchemy_migrate.egg-info/PKG-INFO 2014-09-11 18:42:29.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: sqlalchemy-migrate -Version: 0.9.1 +Version: 0.9.2 Summary: Database schema migration for SQLAlchemy Home-page: http://www.openstack.org/ Author: OpenStack diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/sqlalchemy_migrate.egg-info/requires.txt new/sqlalchemy-migrate-0.9.2/sqlalchemy_migrate.egg-info/requires.txt --- old/sqlalchemy-migrate-0.9.1/sqlalchemy_migrate.egg-info/requires.txt 2014-05-06 16:40:25.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/sqlalchemy_migrate.egg-info/requires.txt 2014-09-11 18:42:29.000000000 +0200 @@ -2,4 +2,5 @@ SQLAlchemy>=0.7.8 decorator six>=1.4.1 +sqlparse Tempita >= 0.4 \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sqlalchemy-migrate-0.9.1/test-requirements.txt new/sqlalchemy-migrate-0.9.2/test-requirements.txt --- old/sqlalchemy-migrate-0.9.1/test-requirements.txt 2014-05-06 16:39:34.000000000 +0200 +++ new/sqlalchemy-migrate-0.9.2/test-requirements.txt 2014-09-11 18:41:49.000000000 +0200 @@ -15,7 +15,7 @@ sphinx>=1.1.2,<1.2 sphinxcontrib_issuetracker testrepository>=0.0.17 -testtools>=0.9.34 +testtools>=0.9.34,<0.9.36 scripttest # NOTE(rpodolyaka): This version identifier is currently necessary as -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org