From 8900c512d4cbbfe422f48c02932d8b2b684e4cd2 Mon Sep 17 00:00:00 2001 From: "jan.dittberner" Date: Sun, 25 Jan 2009 16:28:06 +0000 Subject: [PATCH] PEP-8 clean migrate.changeset, updated CHANGELOG, updated api.rst - code cleanup in the remaining migrate.changeset files - add migrate.changeset.exceptions and migrate.changeset.schema to api.rst - add more information to CHANGELOG --- CHANGELOG | 4 +- docs/api.rst | 14 ++ migrate/changeset/__init__.py | 1 - migrate/changeset/constraint.py | 136 ++++++++---- migrate/changeset/exceptions.py | 15 +- migrate/changeset/schema.py | 362 ++++++++++++++++++-------------- 6 files changed, 327 insertions(+), 205 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b783fce..8e2d2b2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,7 +9,9 @@ - improved support for SQLite - add support for check constraints (EXPERIMENTAL) - print statements removed from APIs -- improved documentation +- improved sphinx based documentation +- removal of old commented code +- PEP-8 clean code 0.4.5 - work by Christian Simms to compare metadata against databases diff --git a/docs/api.rst b/docs/api.rst index 2de1f53..b5803d6 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -64,6 +64,20 @@ Module :mod:`visitor ` .. automodule:: migrate.changeset.databases.visitor :members: +Module :mod:`exceptions ` +------------------------------------------------------- + +.. automodule:: migrate.changeset.exceptions + :members: + :synopsis: Changeset exception classes + +Module :mod:`schema ` +----------------------------------------------- + +.. automodule:: migrate.changeset.schema + :members: + :synopsis: Schema changeset handling functions + Module :mod:`migrate.versioning` ================================ diff --git a/migrate/changeset/__init__.py b/migrate/changeset/__init__.py index d743e4e..a9d1772 100644 --- a/migrate/changeset/__init__.py +++ b/migrate/changeset/__init__.py @@ -6,4 +6,3 @@ """ from migrate.changeset.schema import * from migrate.changeset.constraint import * - diff --git a/migrate/changeset/constraint.py b/migrate/changeset/constraint.py index 96d12b2..56a630f 100644 --- a/migrate/changeset/constraint.py +++ b/migrate/changeset/constraint.py @@ -1,68 +1,108 @@ +""" + This module defines standalone schema constraint classes. +""" import sqlalchemy from sqlalchemy import schema + class ConstraintChangeset(object): - def _normalize_columns(self,cols,fullname=False): - """Given: column objects or names; return col names and (maybe) a table""" + """Base class for Constraint classes. + """ + + def _normalize_columns(self, cols, fullname=False): + """Given: column objects or names; return col names and + (maybe) a table""" colnames = [] table = None for col in cols: - if isinstance(col,schema.Column): + if isinstance(col, schema.Column): if col.table is not None and table is None: table = col.table if fullname: - col = '.'.join((col.table.name,col.name)) + col = '.'.join((col.table.name, col.name)) else: col = col.name colnames.append(col) - return colnames,table - def create(self,engine=None): + return colnames, table + + def create(self, engine=None): + """Create the constraint in the database. + + :param engine: the database engine to use. If this is + :keyword:`None` the instance's engine will be used + :type engine: :class:`sqlalchemy.engine.base.Engine` + """ if engine is None: engine = self.engine engine.create(self) - def drop(self,engine=None): + + def drop(self, engine=None): + """Drop the constraint from the database. + + :param engine: the database engine to use. If this is + :keyword:`None` the instance's engine will be used + :type engine: :class:`sqlalchemy.engine.base.Engine` + """ if engine is None: engine = self.engine - #if self.name is None: - # self.name = self.autoname() engine.drop(self) + def _derived_metadata(self): return self.table._derived_metadata() - def accept_schema_visitor(self,visitor,*p,**k): + + def accept_schema_visitor(self, visitor, *p, **k): + """ + :raises: :exc:`NotImplementedError` if this method is not \ +overridden by a subclass + """ raise NotImplementedError() - def _accept_schema_visitor(self,visitor,func,*p,**k): + + def _accept_schema_visitor(self, visitor, func, *p, **k): """Call the visitor only if it defines the given function""" try: - func = getattr(visitor,func) + func = getattr(visitor, func) except AttributeError: return return func(self) + def autoname(self): + """Automatically generate a name for the constraint instance. + + Subclasses must implement this method. + + :raises: :exc:`NotImplementedError` if this method is not \ +overridden by a subclass + """ raise NotImplementedError() -def _engine_run_visitor(engine,visitorcallable,element,**kwargs): + +def _engine_run_visitor(engine, visitorcallable, element, **kwargs): conn = engine.connect() try: element.accept_schema_visitor(visitorcallable(conn)) finally: conn.close() - -class PrimaryKeyConstraint(ConstraintChangeset,schema.PrimaryKeyConstraint): - def __init__(self,*cols,**kwargs): - colnames,table = self._normalize_columns(cols) - table = kwargs.pop('table',table) - super(PrimaryKeyConstraint,self).__init__(*colnames,**kwargs) + + +class PrimaryKeyConstraint(ConstraintChangeset, schema.PrimaryKeyConstraint): + """Primary key constraint class.""" + + def __init__(self, *cols, **kwargs): + colnames, table = self._normalize_columns(cols) + table = kwargs.pop('table', table) + super(PrimaryKeyConstraint, self).__init__(*colnames, **kwargs) if table is not None: self._set_parent(table) - def _set_parent(self,table): + def _set_parent(self, table): self.table = table - return super(ConstraintChangeset,self)._set_parent(table) + return super(ConstraintChangeset, self)._set_parent(table) def create(self, *args, **kwargs): from migrate.changeset.databases.visitor import get_engine_visitor - visitorcallable = get_engine_visitor(self.table.bind,'constraintgenerator') - _engine_run_visitor (self.table.bind, visitorcallable, self) + visitorcallable = get_engine_visitor(self.table.bind, + 'constraintgenerator') + _engine_run_visitor(self.table.bind, visitorcallable, self) def autoname(self): """Mimic the database's automatic constraint names""" @@ -71,24 +111,29 @@ class PrimaryKeyConstraint(ConstraintChangeset,schema.PrimaryKeyConstraint): ) return ret - def drop(self,*args,**kwargs): + def drop(self, *args, **kwargs): from migrate.changeset.databases.visitor import get_engine_visitor - visitorcallable = get_engine_visitor(self.table.bind,'constraintdropper') - _engine_run_visitor (self.table.bind, visitorcallable, self) + visitorcallable = get_engine_visitor(self.table.bind, + 'constraintdropper') + _engine_run_visitor(self.table.bind, visitorcallable, self) self.columns.clear() return self - def accept_schema_visitor(self,visitor,*p,**k): - #return visitor.visit_constraint(self,*p,**k) + def accept_schema_visitor(self, visitor, *p, **k): func = 'visit_migrate_primary_key_constraint' - return self._accept_schema_visitor(visitor,func,*p,**k) + return self._accept_schema_visitor(visitor, func, *p, **k) -class ForeignKeyConstraint(ConstraintChangeset,schema.ForeignKeyConstraint): - def __init__(self,columns,refcolumns,*p,**k): - colnames,table = self._normalize_columns(columns) - table = k.pop('table',table) - refcolnames,reftable = self._normalize_columns(refcolumns,fullname=True) - super(ForeignKeyConstraint,self).__init__(colnames,refcolnames,*p,**k) + +class ForeignKeyConstraint(ConstraintChangeset, schema.ForeignKeyConstraint): + """Foreign key constraint class.""" + + def __init__(self, columns, refcolumns, *p, **k): + colnames, table = self._normalize_columns(columns) + table = k.pop('table', table) + refcolnames, reftable = self._normalize_columns(refcolumns, + fullname=True) + super(ForeignKeyConstraint, self).__init__(colnames, refcolnames, *p, + **k) if table is not None: self._set_parent(table) @@ -99,7 +144,7 @@ class ForeignKeyConstraint(ConstraintChangeset,schema.ForeignKeyConstraint): def _get_reftable(self): return self.referenced[0].table reftable = property(_get_reftable) - + def autoname(self): """Mimic the database's automatic constraint names""" ret = "%(table)s_%(reftable)s_fkey"%dict( @@ -110,22 +155,27 @@ class ForeignKeyConstraint(ConstraintChangeset,schema.ForeignKeyConstraint): def create(self, *args, **kwargs): from migrate.changeset.databases.visitor import get_engine_visitor - visitorcallable = get_engine_visitor(self.table.bind,'constraintgenerator') - _engine_run_visitor (self.table.bind, visitorcallable, self) + visitorcallable = get_engine_visitor(self.table.bind, + 'constraintgenerator') + _engine_run_visitor(self.table.bind, visitorcallable, self) return self - def drop(self,*args,**kwargs): + def drop(self, *args, **kwargs): from migrate.changeset.databases.visitor import get_engine_visitor - visitorcallable = get_engine_visitor(self.table.bind,'constraintdropper') - _engine_run_visitor (self.table.bind, visitorcallable, self) + visitorcallable = get_engine_visitor(self.table.bind, + 'constraintdropper') + _engine_run_visitor(self.table.bind, visitorcallable, self) self.columns.clear() return self - def accept_schema_visitor(self,visitor,*p,**k): + def accept_schema_visitor(self, visitor, *p, **k): func = 'visit_migrate_foreign_key_constraint' - return self._accept_schema_visitor(visitor,func,*p,**k) + return self._accept_schema_visitor(visitor, func, *p, **k) + class CheckConstraint(ConstraintChangeset, schema.CheckConstraint): + """Check constraint class.""" + def __init__(self, sqltext, *args, **kwargs): cols = kwargs.pop('columns') colnames, table = self._normalize_columns(cols) diff --git a/migrate/changeset/exceptions.py b/migrate/changeset/exceptions.py index fc08c7a..d4df426 100644 --- a/migrate/changeset/exceptions.py +++ b/migrate/changeset/exceptions.py @@ -1,11 +1,24 @@ +""" + This module provides exception classes. +""" class Error(Exception): + """ + Changeset error. + """ pass + class NotSupportedError(Error): + """ + Not supported error. + """ pass + class InvalidConstraintError(Error): + """ + Invalid constraint error. + """ pass - diff --git a/migrate/changeset/schema.py b/migrate/changeset/schema.py index bb78d9e..6c1cdf7 100644 --- a/migrate/changeset/schema.py +++ b/migrate/changeset/schema.py @@ -1,3 +1,6 @@ +""" + Schema module providing common schema operations. +""" import re import sqlalchemy from migrate.changeset.databases.visitor import get_engine_visitor @@ -11,60 +14,72 @@ __all__ = [ ] -def create_column(column,table=None,*p,**k): +def create_column(column, table=None, *p, **k): if table is not None: - return table.create_column(column,*p,**k) - return column.create(*p,**k) + return table.create_column(column, *p, **k) + return column.create(*p, **k) -def drop_column(column,table=None,*p,**k): + +def drop_column(column, table=None, *p, **k): if table is not None: - return table.drop_column(column,*p,**k) - return column.drop(*p,**k) + return table.drop_column(column, *p, **k) + return column.drop(*p, **k) -def _to_table(table,engine=None): - if isinstance(table,sqlalchemy.Table): + +def _to_table(table, engine=None): + if isinstance(table, sqlalchemy.Table): return table # Given: table name, maybe an engine meta = sqlalchemy.MetaData() if engine is not None: - meta.bind = engine #meta.connect(engine) - return sqlalchemy.Table(table,meta) -def _to_index(index,table=None,engine=None): - if isinstance(index,sqlalchemy.Index): + meta.bind = engine + return sqlalchemy.Table(table, meta) + + +def _to_index(index, table=None, engine=None): + if isinstance(index, sqlalchemy.Index): return index # Given: index name; table name required - table = _to_table(table,engine) + table = _to_table(table, engine) ret = sqlalchemy.Index(index) ret.table = table return ret - -def rename_table(table,name,engine=None): - """Rename a table, given the table's current name and the new name.""" - table = _to_table(table,engine) + + +def rename_table(table, name, engine=None): + """Rename a table, given the table's current name and the new + name.""" + table = _to_table(table, engine) table.rename(name) -def rename_index(index,name,table=None,engine=None): - """Rename an index - Takes an index name/object, a table name/object, and an engine. Engine and - table aren't required if an index object is given. + +def rename_index(index, name, table=None, engine=None): + """Rename an index. + + Takes an index name/object, a table name/object, and an + engine. Engine and table aren't required if an index object is + given. """ - index = _to_index(index,table,engine) + index = _to_index(index, table, engine) index.rename(name) -def _engine_run_visitor(engine,visitorcallable,element,**kwargs): +def _engine_run_visitor(engine, visitorcallable, element, **kwargs): conn = engine.connect() try: - element.accept_schema_visitor(visitorcallable(engine.dialect,connection=conn)) + element.accept_schema_visitor(visitorcallable(engine.dialect, + connection=conn)) finally: conn.close() -def alter_column(*p,**k): - """Alter a column - Parameters: column name, table name, an engine, and the - properties of that column to change + +def alter_column(*p, **k): + """Alter a column. + + Parameters: column name, table name, an engine, and the properties + of that column to change """ - if len(p) and isinstance(p[0],sqlalchemy.Column): + if len(p) and isinstance(p[0], sqlalchemy.Column): col = p[0] else: col = None @@ -73,29 +88,33 @@ def alter_column(*p,**k): if 'engine' not in k: k['engine'] = k['table'].bind engine = k['engine'] - delta = _ColumnDelta(*p,**k) - visitorcallable = get_engine_visitor(engine,'schemachanger') - _engine_run_visitor(engine,visitorcallable,delta) + delta = _ColumnDelta(*p, **k) + visitorcallable = get_engine_visitor(engine, 'schemachanger') + _engine_run_visitor(engine, visitorcallable, delta) # Update column if col is not None: - # Special case: change column key on rename, if key not explicit + # Special case: change column key on rename, if key not + # explicit + # # Used by SA : table.c.[key] # - # This fails if the key was explit AND equal to the column name. - # (It changes the key name when it shouldn't.) + # This fails if the key was explit AND equal to the column + # name. (It changes the key name when it shouldn't.) + # # Not much we can do about it. if 'name' in delta.keys(): if (col.name == col.key): newname = delta['name'] del col.table.c[col.key] - setattr(col,'key',newname) + setattr(col, 'key', newname) col.table.c[col.key] = col # Change all other attrs - for key,val in delta.iteritems(): - setattr(col,key,val) + for key, val in delta.iteritems(): + setattr(col, key, val) -def _normalize_table(column,table): + +def _normalize_table(column, table): if table is not None: if table is not column.table: # This is a bit of a hack: we end up with dupe PK columns here @@ -108,45 +127,49 @@ def _normalize_table(column,table): class _WrapRename(object): - def __init__(self,item,name): + + def __init__(self, item, name): self.item = item self.name = name - def accept_schema_visitor(self,visitor): - if isinstance(self.item,sqlalchemy.Table): + def accept_schema_visitor(self, visitor): + if isinstance(self.item, sqlalchemy.Table): suffix = 'table' - elif isinstance(self.item,sqlalchemy.Column): + elif isinstance(self.item, sqlalchemy.Column): suffix = 'column' - elif isinstance(self.item,sqlalchemy.Index): + elif isinstance(self.item, sqlalchemy.Index): suffix = 'index' - funcname = 'visit_%s'%suffix - func = getattr(visitor,funcname) - param = self.item,self.name + funcname = 'visit_%s' % suffix + func = getattr(visitor, funcname) + param = self.item, self.name return func(param) + class _ColumnDelta(dict): """Extracts the differences between two columns/column-parameters""" - def __init__(self,*p,**k): - """Extract ALTER-able differences from two columns + + def __init__(self, *p, **k): + """Extract ALTER-able differences from two columns. + May receive parameters arranged in several different ways: - * old_column_object,new_column_object,*parameters - Identifies attributes that differ between the two columns. - Parameters specified outside of either column are always executed - and override column differences. - * column_object,[current_name,]*parameters - Parameters specified are changed; table name is extracted from - column object. - Name is changed to column_object.name from current_name, if - current_name is specified. If not specified, name is unchanged. - * current_name,table,*parameters - 'table' may be either an object or a name + * old_column_object,new_column_object,*parameters Identifies + attributes that differ between the two columns. + Parameters specified outside of either column are always + executed and override column differences. + * column_object,[current_name,]*parameters Parameters + specified are changed; table name is extracted from column + object. Name is changed to column_object.name from + current_name, if current_name is specified. If not + specified, name is unchanged. + * current_name,table,*parameters 'table' may be either an + object or a name """ # Things are initialized differently depending on how many column # parameters are given. Figure out how many and call the appropriate # method. - if len(p) >= 1 and isinstance(p[0],sqlalchemy.Column): + if len(p) >= 1 and isinstance(p[0], sqlalchemy.Column): # At least one column specified - if len(p) >= 2 and isinstance(p[1],sqlalchemy.Column): + if len(p) >= 2 and isinstance(p[1], sqlalchemy.Column): # Two columns specified func = self._init_2col else: @@ -155,124 +178,138 @@ class _ColumnDelta(dict): else: # Zero columns specified func = self._init_0col - diffs = func(*p,**k) + diffs = func(*p, **k) self._set_diffs(diffs) # Column attributes that can be altered - diff_keys = ('name','type','nullable','default','server_default','primary_key','foreign_key') + diff_keys = ('name', 'type', 'nullable', 'default', 'server_default', + 'primary_key', 'foreign_key') def _get_table_name(self): - if isinstance(self._table,basestring): + if isinstance(self._table, basestring): ret = self._table else: ret = self._table.name return ret table_name = property(_get_table_name) - + def _get_table(self): - if isinstance(self._table,basestring): + if isinstance(self._table, basestring): ret = None else: ret = self._table return ret table = property(_get_table) - def _init_0col(self,current_name,*p,**k): - p,k = self._init_normalize_params(p,k) + def _init_0col(self, current_name, *p, **k): + p, k = self._init_normalize_params(p, k) table = k.pop('table') self.current_name = current_name self._table = table return k - def _init_1col(self,col,*p,**k): - p,k = self._init_normalize_params(p,k) - self._table = k.pop('table',None) or col.table + + def _init_1col(self, col, *p, **k): + p, k = self._init_normalize_params(p, k) + self._table = k.pop('table', None) or col.table self.result_column = col.copy() if 'current_name' in k: # Renamed self.current_name = k.pop('current_name') - k.setdefault('name',col.name) + k.setdefault('name', col.name) else: self.current_name = col.name return k - def _init_2col(self,start_col,end_col,*p,**k): - p,k = self._init_normalize_params(p,k) + + def _init_2col(self, start_col, end_col, *p, **k): + p, k = self._init_normalize_params(p, k) self.result_column = start_col.copy() - self._table = k.pop('table',None) or start_col.table or end_col.table + self._table = k.pop('table', None) or start_col.table \ + or end_col.table self.current_name = start_col.name - for key in ('name','nullable','default','server_default','primary_key','foreign_key'): - val = getattr(end_col,key,None) - if getattr(start_col,key,None) != val: - k.setdefault(key,val) - if not self.column_types_eq(start_col.type,end_col.type): - k.setdefault('type',end_col.type) + for key in ('name', 'nullable', 'default', 'server_default', + 'primary_key', 'foreign_key'): + val = getattr(end_col, key, None) + if getattr(start_col, key, None) != val: + k.setdefault(key, val) + if not self.column_types_eq(start_col.type, end_col.type): + k.setdefault('type', end_col.type) return k - def _init_normalize_params(self,p,k): + + def _init_normalize_params(self, p, k): p = list(p) if len(p): - k.setdefault('name',p.pop(0)) + k.setdefault('name', p.pop(0)) if len(p): - k.setdefault('type',p.pop(0)) + k.setdefault('type', p.pop(0)) # TODO: sequences? FKs? - return p,k - def _set_diffs(self,diffs): + return p, k + + def _set_diffs(self, diffs): for key in self.diff_keys: if key in diffs: self[key] = diffs[key] - if getattr(self,'result_column',None) is not None: - setattr(self.result_column,key,diffs[key]) - def column_types_eq(self,this,that): - ret = isinstance(this,that.__class__) - ret = ret or isinstance(that,this.__class__) + if getattr(self, 'result_column', None) is not None: + setattr(self.result_column, key, diffs[key]) + + def column_types_eq(self, this, that): + ret = isinstance(this, that.__class__) + ret = ret or isinstance(that, this.__class__) # String length is a special case - if ret and isinstance(that,sqlalchemy.types.String): - ret = (getattr(this,'length',None) == getattr(that,'length',None)) + if ret and isinstance(that, sqlalchemy.types.String): + ret = (getattr(this, 'length', None) == \ + getattr(that, 'length', None)) return ret - def accept_schema_visitor(self,visitor): + def accept_schema_visitor(self, visitor): return visitor.visit_column(self) + class ChangesetTable(object): """Changeset extensions to SQLAlchemy tables.""" - def create_column(self,column): - """Creates a column - The column parameter may be a column definition or the name of a column - in this table. + + def create_column(self, column): + """Creates a column. + + The column parameter may be a column definition or the name of + a column in this table. """ - if not isinstance(column,sqlalchemy.Column): + if not isinstance(column, sqlalchemy.Column): # It's a column name - column = getattr(self.c,str(column)) + column = getattr(self.c, str(column)) column.create(table=self) - - def drop_column(self,column): + + def drop_column(self, column): """Drop a column, given its name or definition.""" - if not isinstance(column,sqlalchemy.Column): + if not isinstance(column, sqlalchemy.Column): # It's a column name try: - column = getattr(self.c,str(column),None) + column = getattr(self.c, str(column), None) except AttributeError: - # That column isn't part of the table. We don't need its entire - # definition to drop the column, just its name, so create a dummy - # column with the same name. + # That column isn't part of the table. We don't need + # its entire definition to drop the column, just its + # name, so create a dummy column with the same name. column = sqlalchemy.Column(str(column)) column.drop(table=self) def _meta_key(self): - return sqlalchemy.schema._get_table_key(self.name,self.schema) + return sqlalchemy.schema._get_table_key(self.name, self.schema) + def deregister(self): """Remove this table from its metadata""" key = self._meta_key() meta = self.metadata if key in meta.tables: del meta.tables[key] - - def rename(self,name,*args,**kwargs): - """Rename this table - This changes both the database name and the name of this Python object + + def rename(self, name, *args, **kwargs): + """Rename this table. + + This changes both the database name and the name of this + Python object """ engine = self.bind - visitorcallable = get_engine_visitor(engine,'schemachanger') - param = _WrapRename(self,name) - #engine._run_visitor(visitorcallable,param,*args,**kwargs) - _engine_run_visitor(engine,visitorcallable,param,*args,**kwargs) + visitorcallable = get_engine_visitor(engine, 'schemachanger') + param = _WrapRename(self, name) + _engine_run_visitor(engine, visitorcallable, param, *args, **kwargs) # Fix metadata registration meta = self.metadata @@ -284,82 +321,89 @@ class ChangesetTable(object): """Fullname should always be up to date""" # Copied from Table constructor if self.schema is not None: - ret = "%s.%s"%(self.schema,self.name) + ret = "%s.%s"%(self.schema, self.name) else: ret = self.name return ret - fullname = property(_get_fullname,(lambda self,val: None)) + + fullname = property(_get_fullname, (lambda self, val: None)) + class ChangesetColumn(object): """Changeset extensions to SQLAlchemy columns""" - def alter(self,*p,**k): - """Alter a column's definition: ALTER TABLE ALTER COLUMN - May supply a new column object, or a list of properties to change. + + def alter(self, *p, **k): + """Alter a column's definition: ``ALTER TABLE ALTER COLUMN``. + + May supply a new column object, or a list of properties to + change. For example; the following are equivalent: - col.alter(Column('myint',Integer,nullable=False)) - col.alter('myint',Integer,nullable=False) - col.alter(name='myint',type=Integer,nullable=False) + col.alter(Column('myint', Integer, nullable=False)) + col.alter('myint', Integer, nullable=False) + col.alter(name='myint', type=Integer, nullable=False) - Column name, type, default, and nullable may be changed here. Note that - for column defaults, only PassiveDefaults are managed by the database - - changing others doesn't make sense. + Column name, type, default, and nullable may be changed + here. Note that for column defaults, only PassiveDefaults are + managed by the database - changing others doesn't make sense. """ if 'table' not in k: k['table'] = self.table if 'engine' not in k: k['engine'] = k['table'].bind - return alter_column(self,*p,**k) + return alter_column(self, *p, **k) - def create(self,table=None,*args,**kwargs): - """Create this column in the database. Assumes the given table exists. - ALTER TABLE ADD COLUMN, for most databases. + def create(self, table=None, *args, **kwargs): + """Create this column in the database. + + Assumes the given table exists. ``ALTER TABLE ADD COLUMN``, + for most databases. """ - table = _normalize_table(self,table) + table = _normalize_table(self, table) engine = table.bind - visitorcallable = get_engine_visitor(engine,'columngenerator') - engine._run_visitor(visitorcallable, self, *args,**kwargs) + visitorcallable = get_engine_visitor(engine, 'columngenerator') + engine._run_visitor(visitorcallable, self, *args, **kwargs) #add in foreign keys if self.foreign_keys: for fk in self.foreign_keys: - visitorcallable = get_engine_visitor(engine,'columnfkgenerator') + visitorcallable = get_engine_visitor(engine, + 'columnfkgenerator') engine._run_visitor(visitorcallable, self, fk=fk) - return self - - def drop(self,table=None,*args,**kwargs): + + def drop(self, table=None, *args, **kwargs): """Drop this column from the database, leaving its table intact. - ALTER TABLE DROP COLUMN, for most databases. + + ``ALTER TABLE DROP COLUMN``, for most databases. """ - table = _normalize_table(self,table) + table = _normalize_table(self, table) engine = table.bind - visitorcallable = get_engine_visitor(engine,'columndropper') - #engine._run_visitor(visitorcallable,self,*args,**kwargs) - engine._run_visitor(lambda dialect, conn: visitorcallable(conn), self, *args, **kwargs) - ## Remove col from table object, too - #del table._columns[self.key] - #if self in table.primary_key: - # table.primary_key.remove(self) + visitorcallable = get_engine_visitor(engine, 'columndropper') + engine._run_visitor(lambda dialect, conn: visitorcallable(conn), + self, *args, **kwargs) return self - + + class ChangesetIndex(object): - """Changeset extensions to SQLAlchemy Indexes""" - def rename(self,name,*args,**kwargs): + """Changeset extensions to SQLAlchemy Indexes.""" + + def rename(self, name, *args, **kwargs): """Change the name of an index. - This changes both the Python object name and the database name. + + This changes both the Python object name and the database + name. """ engine = self.table.bind - visitorcallable = get_engine_visitor(engine,'schemachanger') - param = _WrapRename(self,name) - #engine._run_visitor(visitorcallable,param,*args,**kwargs) - _engine_run_visitor(engine,visitorcallable,param,*args,**kwargs) + visitorcallable = get_engine_visitor(engine, 'schemachanger') + param = _WrapRename(self, name) + _engine_run_visitor(engine, visitorcallable, param, *args, **kwargs) self.name = name def _patch(): """All the 'ugly' operations that patch SQLAlchemy's internals.""" - sqlalchemy.schema.Table.__bases__ += (ChangesetTable,) - sqlalchemy.schema.Column.__bases__ += (ChangesetColumn,) - sqlalchemy.schema.Index.__bases__ += (ChangesetIndex,) + sqlalchemy.schema.Table.__bases__ += (ChangesetTable, ) + sqlalchemy.schema.Column.__bases__ += (ChangesetColumn, ) + sqlalchemy.schema.Index.__bases__ += (ChangesetIndex, ) _patch()