make migrate.changeset.databases PEP-8 clean and add it to the API docs
This commit is contained in:
parent
728b677e56
commit
eb00570991
45
docs/api.rst
45
docs/api.rst
@ -9,13 +9,54 @@ Module :mod:`migrate.changeset`
|
||||
:members:
|
||||
:synopsis: Database changeset management
|
||||
|
||||
Module :mod:`migrate.changeset.ansisql`
|
||||
---------------------------------------
|
||||
Module :mod:`ansisql <migrate.changeset.ansisql>`
|
||||
-------------------------------------------------
|
||||
|
||||
.. automodule:: migrate.changeset.ansisql
|
||||
:members:
|
||||
:synopsis: Standard SQL implementation for altering database schemas
|
||||
|
||||
Module :mod:`databases <migrate.changeset.databases>`
|
||||
-----------------------------------------------------
|
||||
|
||||
.. automodule:: migrate.changeset.databases
|
||||
:members:
|
||||
:synopsis: Database specific changeset implementations
|
||||
|
||||
Module :mod:`mysql <migrate.changeset.databases.mysql>`
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: migrate.changeset.databases.mysql
|
||||
:members:
|
||||
:synopsis: MySQL database specific changeset implementations
|
||||
|
||||
Module :mod:`oracle <migrate.changeset.databases.oracle>`
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: migrate.changeset.databases.oracle
|
||||
:members:
|
||||
:synopsis: Oracle database specific changeset implementations
|
||||
|
||||
Module :mod:`postgres <migrate.changeset.databases.postgres>`
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: migrate.changeset.databases.postgres
|
||||
:members:
|
||||
:synopsis: PostgreSQL database specific changeset implementations
|
||||
|
||||
Module :mod:`sqlite <migrate.changeset.databases.slite>`
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: migrate.changeset.databases.sqlite
|
||||
:members:
|
||||
:synopsis: SQLite database specific changeset implementations
|
||||
|
||||
Module :mod:`visitor <migrate.changeset.databases.visitor>`
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: migrate.changeset.databases.visitor
|
||||
:members:
|
||||
|
||||
Module :mod:`migrate.versioning`
|
||||
================================
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module contains database dialect specific changeset
|
||||
implementations.
|
||||
"""
|
||||
__all__=[
|
||||
'postgres',
|
||||
'sqlite',
|
||||
|
@ -1,20 +1,32 @@
|
||||
"""
|
||||
MySQL database specific implementations of changeset classes.
|
||||
"""
|
||||
|
||||
from migrate.changeset import ansisql, exceptions
|
||||
from sqlalchemy.databases import mysql as sa_base
|
||||
#import sqlalchemy as sa
|
||||
|
||||
MySQLSchemaGenerator = sa_base.MySQLSchemaGenerator
|
||||
|
||||
|
||||
class MySQLColumnGenerator(MySQLSchemaGenerator, ansisql.ANSIColumnGenerator):
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
pass
|
||||
|
||||
|
||||
class MySQLColumnDropper(ansisql.ANSIColumnDropper):
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
|
||||
|
||||
class MySQLSchemaChanger(MySQLSchemaGenerator, ansisql.ANSISchemaChanger):
|
||||
|
||||
def visit_column(self, delta):
|
||||
keys = delta.keys()
|
||||
if 'type' in keys or 'nullable' in keys or 'name' in keys:
|
||||
@ -22,31 +34,41 @@ class MySQLSchemaChanger(MySQLSchemaGenerator,ansisql.ANSISchemaChanger):
|
||||
if 'server_default' in keys:
|
||||
# Column name might have changed above
|
||||
col_name = delta.get('name', delta.current_name)
|
||||
self._run_subvisit(delta,self._visit_column_default,col_name=col_name)
|
||||
self._run_subvisit(delta, self._visit_column_default,
|
||||
col_name=col_name)
|
||||
|
||||
def _visit_column_change(self, table_name, col_name, delta):
|
||||
if not hasattr(delta, 'result_column'):
|
||||
# Mysql needs the whole column definition, not just a lone name/type
|
||||
# Mysql needs the whole column definition, not just a lone
|
||||
# name/type
|
||||
raise exceptions.NotSupportedError(
|
||||
"A column object is required to do this")
|
||||
|
||||
column = delta.result_column
|
||||
if not column.table: column.table = delta.table # needed by get_column_specification
|
||||
# needed by get_column_specification
|
||||
if not column.table:
|
||||
column.table = delta.table
|
||||
colspec = self.get_column_specification(column)
|
||||
self.start_alter_table(table_name)
|
||||
self.append("CHANGE COLUMN ")
|
||||
self.append(col_name)
|
||||
self.append(' ')
|
||||
self.append(colspec)
|
||||
|
||||
def visit_index(self, param):
|
||||
# If MySQL can do this, I can't find how
|
||||
raise exceptions.NotSupportedError("MySQL cannot rename indexes")
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
|
||||
|
||||
class MySQLConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
|
||||
|
||||
class MySQLConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
#def visit_constraint(self,constraint):
|
||||
# if isinstance(constraint,sqlalchemy.schema.PrimaryKeyConstraint):
|
||||
@ -54,6 +76,7 @@ class MySQLConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
# elif isinstance(constraint,sqlalchemy.schema.ForeignKeyConstraint):
|
||||
# return self._visit_constraint_fk(constraint)
|
||||
# return super(MySQLConstraintDropper,self).visit_constraint(constraint)
|
||||
|
||||
def visit_migrate_primary_key_constraint(self, constraint):
|
||||
self.start_alter_table(constraint)
|
||||
self.append("DROP PRIMARY KEY")
|
||||
@ -68,6 +91,7 @@ class MySQLConstraintDropper(ansisql.ANSIConstraintDropper):
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return '%s'%identifier
|
||||
|
||||
|
||||
class MySQLDialect(ansisql.ANSIDialect):
|
||||
columngenerator = MySQLColumnGenerator
|
||||
columndropper = MySQLColumnDropper
|
||||
|
@ -1,54 +1,74 @@
|
||||
"""
|
||||
Oracle database specific implementations of changeset classes.
|
||||
"""
|
||||
|
||||
from migrate.changeset import ansisql, exceptions
|
||||
from sqlalchemy.databases import oracle as sa_base
|
||||
import sqlalchemy as sa
|
||||
|
||||
OracleSchemaGenerator = sa_base.OracleSchemaGenerator
|
||||
|
||||
class OracleColumnGenerator(OracleSchemaGenerator,ansisql.ANSIColumnGenerator):
|
||||
|
||||
class OracleColumnGenerator(OracleSchemaGenerator,
|
||||
ansisql.ANSIColumnGenerator):
|
||||
pass
|
||||
|
||||
|
||||
class OracleColumnDropper(ansisql.ANSIColumnDropper):
|
||||
pass
|
||||
|
||||
|
||||
class OracleSchemaChanger(OracleSchemaGenerator, ansisql.ANSISchemaChanger):
|
||||
|
||||
def get_column_specification(self, column, **kwargs):
|
||||
# Ignore the NOT NULL generated
|
||||
override_nullable = kwargs.pop('override_nullable', None)
|
||||
if override_nullable:
|
||||
orig = column.nullable
|
||||
column.nullable = True
|
||||
ret=super(OracleSchemaChanger,self).get_column_specification(column,**kwargs)
|
||||
ret = super(OracleSchemaChanger, self).get_column_specification(
|
||||
column, **kwargs)
|
||||
if override_nullable:
|
||||
column.nullable = orig
|
||||
return ret
|
||||
|
||||
def visit_column(self, delta):
|
||||
keys = delta.keys()
|
||||
if 'type' in keys or 'nullable' in keys or 'default' in keys or 'server_default' in keys:
|
||||
if 'type' in keys or 'nullable' in keys or 'default' in keys \
|
||||
or 'server_default' in keys:
|
||||
self._run_subvisit(delta, self._visit_column_change)
|
||||
if 'name' in keys:
|
||||
self._run_subvisit(delta, self._visit_column_name)
|
||||
|
||||
def _visit_column_change(self, table_name, col_name, delta):
|
||||
if not hasattr(delta, 'result_column'):
|
||||
# Oracle needs the whole column definition, not just a lone name/type
|
||||
# Oracle needs the whole column definition, not just a
|
||||
# lone name/type
|
||||
raise exceptions.NotSupportedError(
|
||||
"A column object is required to do this")
|
||||
|
||||
column = delta.result_column
|
||||
# Oracle cannot drop a default once created, but it can set it to null.
|
||||
# We'll do that if default=None
|
||||
# http://forums.oracle.com/forums/message.jspa?messageID=1273234#1273234
|
||||
dropdefault_hack = (column.server_default is None and 'server_default' in delta.keys())
|
||||
# Oracle apparently doesn't like it when we say "not null" if the
|
||||
# column's already not null. Fudge it, so we don't need a new function
|
||||
notnull_hack = ((not column.nullable) and ('nullable' not in delta.keys()))
|
||||
# We need to specify NULL if we're removing a NOT NULL constraint
|
||||
# Oracle cannot drop a default once created, but it can set it
|
||||
# to null. We'll do that if default=None
|
||||
# http://forums.oracle.com/forums/message.jspa?\
|
||||
# messageID=1273234#1273234
|
||||
dropdefault_hack = (column.server_default is None \
|
||||
and 'server_default' in delta.keys())
|
||||
# Oracle apparently doesn't like it when we say "not null" if
|
||||
# the column's already not null. Fudge it, so we don't need a
|
||||
# new function
|
||||
notnull_hack = ((not column.nullable) \
|
||||
and ('nullable' not in delta.keys()))
|
||||
# We need to specify NULL if we're removing a NOT NULL
|
||||
# constraint
|
||||
null_hack = (column.nullable and ('nullable' in delta.keys()))
|
||||
|
||||
|
||||
if dropdefault_hack:
|
||||
column.server_default = sa.PassiveDefault(sa.sql.null())
|
||||
if notnull_hack:
|
||||
column.nullable = True
|
||||
colspec=self.get_column_specification(column,override_nullable=null_hack)
|
||||
colspec=self.get_column_specification(column,
|
||||
override_nullable=null_hack)
|
||||
if null_hack:
|
||||
colspec += ' NULL'
|
||||
if notnull_hack:
|
||||
@ -59,18 +79,28 @@ class OracleSchemaChanger(OracleSchemaGenerator,ansisql.ANSISchemaChanger):
|
||||
self.start_alter_table(table_name)
|
||||
self.append("MODIFY ")
|
||||
self.append(colspec)
|
||||
|
||||
|
||||
class OracleConstraintCommon(object):
|
||||
|
||||
def get_constraint_name(self, cons):
|
||||
# Oracle constraints can't guess their name like other DBs
|
||||
if not cons.name:
|
||||
raise exceptions.NotSupportedError(
|
||||
"Oracle constraint names must be explicitly stated")
|
||||
return cons.name
|
||||
class OracleConstraintGenerator(OracleConstraintCommon,ansisql.ANSIConstraintGenerator):
|
||||
|
||||
|
||||
class OracleConstraintGenerator(OracleConstraintCommon,
|
||||
ansisql.ANSIConstraintGenerator):
|
||||
pass
|
||||
class OracleConstraintDropper(OracleConstraintCommon,ansisql.ANSIConstraintDropper):
|
||||
|
||||
|
||||
class OracleConstraintDropper(OracleConstraintCommon,
|
||||
ansisql.ANSIConstraintDropper):
|
||||
pass
|
||||
|
||||
|
||||
class OracleDialect(ansisql.ANSIDialect):
|
||||
columngenerator = OracleColumnGenerator
|
||||
columndropper = OracleColumnDropper
|
||||
|
@ -1,44 +1,53 @@
|
||||
"""
|
||||
`PostgreSQL`_ database specific implementations of changeset classes.
|
||||
|
||||
.. _`PostgreSQL`: http://www.postgresql.org/
|
||||
"""
|
||||
from migrate.changeset import ansisql
|
||||
from sqlalchemy.databases import postgres as sa_base
|
||||
#import sqlalchemy as sa
|
||||
|
||||
|
||||
PGSchemaGenerator = sa_base.PGSchemaGenerator
|
||||
|
||||
|
||||
class PGSchemaGeneratorMixin(object):
|
||||
"""Common code used by the PostgreSQL specific classes."""
|
||||
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return identifier
|
||||
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '"%s"'%identifier
|
||||
|
||||
class PGColumnGenerator(PGSchemaGenerator,ansisql.ANSIColumnGenerator, PGSchemaGeneratorMixin):
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return identifier
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '"%s"'%identifier
|
||||
|
||||
class PGColumnGenerator(PGSchemaGenerator, ansisql.ANSIColumnGenerator,
|
||||
PGSchemaGeneratorMixin):
|
||||
"""PostgreSQL column generator implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGColumnDropper(ansisql.ANSIColumnDropper, PGSchemaGeneratorMixin):
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return identifier
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '"%s"'%identifier
|
||||
"""PostgreSQL column dropper implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGSchemaChanger(ansisql.ANSISchemaChanger, PGSchemaGeneratorMixin):
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return identifier
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '"%s"'%identifier
|
||||
"""PostgreSQL schema changer implementation."""
|
||||
pass
|
||||
|
||||
class PGConstraintGenerator(ansisql.ANSIConstraintGenerator, PGSchemaGeneratorMixin):
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return identifier
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '"%s"'%identifier
|
||||
|
||||
class PGConstraintDropper(ansisql.ANSIConstraintDropper, PGSchemaGeneratorMixin):
|
||||
def _do_quote_table_identifier(self, identifier):
|
||||
return identifier
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '"%s"'%identifier
|
||||
class PGConstraintGenerator(ansisql.ANSIConstraintGenerator,
|
||||
PGSchemaGeneratorMixin):
|
||||
"""PostgreSQL constraint generator implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGConstraintDropper(ansisql.ANSIConstraintDropper,
|
||||
PGSchemaGeneratorMixin):
|
||||
"""PostgreSQL constaint dropper implementation."""
|
||||
pass
|
||||
|
||||
|
||||
class PGDialect(ansisql.ANSIDialect):
|
||||
columngenerator = PGColumnGenerator
|
||||
|
@ -1,3 +1,8 @@
|
||||
"""
|
||||
`SQLite`_ database specific implementations of changeset classes.
|
||||
|
||||
.. _`SQLite`: http://www.sqlite.org/
|
||||
"""
|
||||
from migrate.changeset import ansisql, constraint, exceptions
|
||||
from sqlalchemy.databases import sqlite as sa_base
|
||||
from sqlalchemy import Table, MetaData
|
||||
@ -5,7 +10,9 @@ from sqlalchemy import Table, MetaData
|
||||
|
||||
SQLiteSchemaGenerator = sa_base.SQLiteSchemaGenerator
|
||||
|
||||
|
||||
class SQLiteHelper(object):
|
||||
|
||||
def visit_column(self, param):
|
||||
try:
|
||||
table = self._to_table(param.table)
|
||||
@ -24,16 +31,22 @@ class SQLiteHelper(object):
|
||||
self.append('DROP TABLE migration_tmp')
|
||||
self.execute()
|
||||
|
||||
class SQLiteColumnGenerator(SQLiteSchemaGenerator,ansisql.ANSIColumnGenerator):
|
||||
|
||||
class SQLiteColumnGenerator(SQLiteSchemaGenerator,
|
||||
ansisql.ANSIColumnGenerator):
|
||||
pass
|
||||
|
||||
|
||||
class SQLiteColumnDropper(SQLiteHelper, ansisql.ANSIColumnDropper):
|
||||
|
||||
def _modify_table(self, table, column):
|
||||
del table.columns[column.name]
|
||||
columns = ','.join([c.name for c in table.columns])
|
||||
return 'INSERT INTO %(table_name)s SELECT ' + columns + ' from migration_tmp'
|
||||
return 'INSERT INTO %(table_name)s SELECT %s from migration_tmp' % \
|
||||
','.join([c.name for c in table.columns])
|
||||
|
||||
|
||||
class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
|
||||
|
||||
def _not_supported(self, op):
|
||||
raise exceptions.NotSupportedError("SQLite does not support "
|
||||
"%s; see http://www.sqlite.org/lang_altertable.html"%op)
|
||||
@ -50,7 +63,9 @@ class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
|
||||
def _do_quote_column_identifier(self, identifier):
|
||||
return '"%s"'%identifier
|
||||
|
||||
|
||||
class SQLiteConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
|
||||
def visit_migrate_primary_key_constraint(self, constraint):
|
||||
tmpl = "CREATE UNIQUE INDEX %s ON %s ( %s )"
|
||||
cols = ','.join([c.name for c in constraint.columns])
|
||||
@ -60,7 +75,9 @@ class SQLiteConstraintGenerator(ansisql.ANSIConstraintGenerator):
|
||||
self.append(msg)
|
||||
self.execute()
|
||||
|
||||
|
||||
class SQLiteConstraintDropper(ansisql.ANSIColumnDropper):
|
||||
|
||||
def visit_migrate_primary_key_constraint(self, constraint):
|
||||
tmpl = "DROP INDEX %s "
|
||||
name = constraint.name
|
||||
@ -68,6 +85,7 @@ class SQLiteConstraintDropper(ansisql.ANSIColumnDropper):
|
||||
self.append(msg)
|
||||
self.execute()
|
||||
|
||||
|
||||
class SQLiteDialect(ansisql.ANSIDialect):
|
||||
columngenerator = SQLiteColumnGenerator
|
||||
columndropper = SQLiteColumnDropper
|
||||
|
@ -1,3 +1,6 @@
|
||||
"""
|
||||
Module for visitor class mapping.
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
from migrate.changeset.databases import sqlite, postgres, mysql, oracle
|
||||
from migrate.changeset import ansisql
|
||||
@ -11,10 +14,21 @@ dialects = {
|
||||
sa.databases.oracle.OracleDialect: oracle.OracleDialect,
|
||||
}
|
||||
|
||||
|
||||
def get_engine_visitor(engine, name):
|
||||
"""
|
||||
Get the visitor implementation for the given database engine.
|
||||
"""
|
||||
return get_dialect_visitor(engine.dialect, name)
|
||||
|
||||
|
||||
def get_dialect_visitor(sa_dialect, name):
|
||||
"""
|
||||
Get the visitor implementation for the given dialect.
|
||||
|
||||
Finds the visitor implementation based on the dialect class and
|
||||
returns and instance initialized with the given name.
|
||||
"""
|
||||
sa_dialect_cls = sa_dialect.__class__
|
||||
migrate_dialect_cls = dialects[sa_dialect_cls]
|
||||
return migrate_dialect_cls.visitor(name)
|
||||
|
Loading…
x
Reference in New Issue
Block a user