##// END OF EJS Templates
updated sqlalchemy migrate to latest version
marcink -
r1061:9bb609d1 beta
parent child Browse files
Show More
@@ -28,7 +28,7 b' class ConstraintChangeset(object):'
28 def __do_imports(self, visitor_name, *a, **kw):
28 def __do_imports(self, visitor_name, *a, **kw):
29 engine = kw.pop('engine', self.table.bind)
29 engine = kw.pop('engine', self.table.bind)
30 from rhodecode.lib.dbmigrate.migrate.changeset.databases.visitor import (get_engine_visitor,
30 from rhodecode.lib.dbmigrate.migrate.changeset.databases.visitor import (get_engine_visitor,
31 run_single_visitor)
31 run_single_visitor)
32 visitorcallable = get_engine_visitor(engine, visitor_name)
32 visitorcallable = get_engine_visitor(engine, visitor_name)
33 run_single_visitor(engine, visitorcallable, self, *a, **kw)
33 run_single_visitor(engine, visitorcallable, self, *a, **kw)
34
34
@@ -2,7 +2,7 b''
2 Firebird database specific implementations of changeset classes.
2 Firebird database specific implementations of changeset classes.
3 """
3 """
4 from sqlalchemy.databases import firebird as sa_base
4 from sqlalchemy.databases import firebird as sa_base
5
5 from sqlalchemy.schema import PrimaryKeyConstraint
6 from rhodecode.lib.dbmigrate.migrate import exceptions
6 from rhodecode.lib.dbmigrate.migrate import exceptions
7 from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06
7 from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06
8
8
@@ -27,13 +27,32 b' class FBColumnDropper(ansisql.ANSIColumn'
27 if column.table.primary_key.columns.contains_column(column):
27 if column.table.primary_key.columns.contains_column(column):
28 column.table.primary_key.drop()
28 column.table.primary_key.drop()
29 # TODO: recreate primary key if it references more than this column
29 # TODO: recreate primary key if it references more than this column
30 if column.unique or getattr(column, 'unique_name', None):
31 for cons in column.table.constraints:
32 if cons.contains_column(column):
33 cons.drop()
34 # TODO: recreate unique constraint if it refenrences more than this column
35
30
36 table = self.start_alter_table(column)
31 for index in column.table.indexes:
32 # "column in index.columns" causes problems as all
33 # column objects compare equal and return a SQL expression
34 if column.name in [col.name for col in index.columns]:
35 index.drop()
36 # TODO: recreate index if it references more than this column
37
38 for cons in column.table.constraints:
39 if isinstance(cons,PrimaryKeyConstraint):
40 # will be deleted only when the column its on
41 # is deleted!
42 continue
43
44 if SQLA_06:
45 should_drop = column.name in cons.columns
46 else:
47 should_drop = cons.contains_column(column) and cons.name
48 if should_drop:
49 self.start_alter_table(column)
50 self.append("DROP CONSTRAINT ")
51 self.append(self.preparer.format_constraint(cons))
52 self.execute()
53 # TODO: recreate unique constraint if it refenrences more than this column
54
55 self.start_alter_table(column)
37 self.append('DROP %s' % self.preparer.format_column(column))
56 self.append('DROP %s' % self.preparer.format_column(column))
38 self.execute()
57 self.execute()
39
58
@@ -80,10 +80,17 b' class SQLiteColumnDropper(SQLiteHelper, '
80 """SQLite ColumnDropper"""
80 """SQLite ColumnDropper"""
81
81
82 def _modify_table(self, table, column, delta):
82 def _modify_table(self, table, column, delta):
83
83 columns = ' ,'.join(map(self.preparer.format_column, table.columns))
84 columns = ' ,'.join(map(self.preparer.format_column, table.columns))
84 return 'INSERT INTO %(table_name)s SELECT ' + columns + \
85 return 'INSERT INTO %(table_name)s SELECT ' + columns + \
85 ' from migration_tmp'
86 ' from migration_tmp'
86
87
88 def visit_column(self,column):
89 # For SQLite, we *have* to remove the column here so the table
90 # is re-created properly.
91 column.remove_from_table(column.table,unset_table=False)
92 super(SQLiteColumnDropper,self).visit_column(column)
93
87
94
88 class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
95 class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger):
89 """SQLite SchemaChanger"""
96 """SQLite SchemaChanger"""
@@ -29,9 +29,6 b' from rhodecode.lib.dbmigrate.migrate.cha'
29 'ColumnDelta',
29 'ColumnDelta',
30 ]
30 ]
31
31
32 DEFAULT_ALTER_METADATA = True
33
34
35 def create_column(column, table=None, *p, **kw):
32 def create_column(column, table=None, *p, **kw):
36 """Create a column, given the table.
33 """Create a column, given the table.
37
34
@@ -109,19 +106,11 b' def alter_column(*p, **k):'
109 The :class:`~sqlalchemy.engine.base.Engine` to use for table
106 The :class:`~sqlalchemy.engine.base.Engine` to use for table
110 reflection and schema alterations.
107 reflection and schema alterations.
111
108
112 :param alter_metadata:
113 If `True`, which is the default, the
114 :class:`~sqlalchemy.schema.Column` will also modified.
115 If `False`, the :class:`~sqlalchemy.schema.Column` will be left
116 as it was.
117
118 :returns: A :class:`ColumnDelta` instance representing the change.
109 :returns: A :class:`ColumnDelta` instance representing the change.
119
110
120
111
121 """
112 """
122
113
123 k.setdefault('alter_metadata', DEFAULT_ALTER_METADATA)
124
125 if 'table' not in k and isinstance(p[0], sqlalchemy.Column):
114 if 'table' not in k and isinstance(p[0], sqlalchemy.Column):
126 k['table'] = p[0].table
115 k['table'] = p[0].table
127 if 'engine' not in k:
116 if 'engine' not in k:
@@ -135,6 +124,12 b' def alter_column(*p, **k):'
135 MigrateDeprecationWarning
124 MigrateDeprecationWarning
136 )
125 )
137 engine = k['engine']
126 engine = k['engine']
127
128 # enough tests seem to break when metadata is always altered
129 # that this crutch has to be left in until they can be sorted
130 # out
131 k['alter_metadata']=True
132
138 delta = ColumnDelta(*p, **k)
133 delta = ColumnDelta(*p, **k)
139
134
140 visitorcallable = get_engine_visitor(engine, 'schemachanger')
135 visitorcallable = get_engine_visitor(engine, 'schemachanger')
@@ -188,11 +183,10 b' class ColumnDelta(DictMixin, sqlalchemy.'
188 :param table: Table at which current Column should be bound to.\
183 :param table: Table at which current Column should be bound to.\
189 If table name is given, reflection will be used.
184 If table name is given, reflection will be used.
190 :type table: string or Table instance
185 :type table: string or Table instance
191 :param alter_metadata: If True, it will apply changes to metadata.
186
192 :type alter_metadata: bool
187 :param metadata: A :class:`MetaData` instance to store
193 :param metadata: If `alter_metadata` is true, \
188 reflected table names
194 metadata is used to reflect table names into
189
195 :type metadata: :class:`MetaData` instance
196 :param engine: When reflecting tables, either engine or metadata must \
190 :param engine: When reflecting tables, either engine or metadata must \
197 be specified to acquire engine object.
191 be specified to acquire engine object.
198 :type engine: :class:`Engine` instance
192 :type engine: :class:`Engine` instance
@@ -213,7 +207,11 b' class ColumnDelta(DictMixin, sqlalchemy.'
213 __visit_name__ = 'column'
207 __visit_name__ = 'column'
214
208
215 def __init__(self, *p, **kw):
209 def __init__(self, *p, **kw):
210 # 'alter_metadata' is not a public api. It exists purely
211 # as a crutch until the tests that fail when 'alter_metadata'
212 # behaviour always happens can be sorted out
216 self.alter_metadata = kw.pop("alter_metadata", False)
213 self.alter_metadata = kw.pop("alter_metadata", False)
214
217 self.meta = kw.pop("metadata", None)
215 self.meta = kw.pop("metadata", None)
218 self.engine = kw.pop("engine", None)
216 self.engine = kw.pop("engine", None)
219
217
@@ -237,17 +235,19 b' class ColumnDelta(DictMixin, sqlalchemy.'
237 self.apply_diffs(diffs)
235 self.apply_diffs(diffs)
238
236
239 def __repr__(self):
237 def __repr__(self):
240 return '<ColumnDelta altermetadata=%r, %s>' % (self.alter_metadata,
238 return '<ColumnDelta altermetadata=%r, %s>' % (
241 super(ColumnDelta, self).__repr__())
239 self.alter_metadata,
242
240 super(ColumnDelta, self).__repr__()
241 )
242
243 def __getitem__(self, key):
243 def __getitem__(self, key):
244 if key not in self.keys():
244 if key not in self.keys():
245 raise KeyError("No such diff key, available: %s" % self.diffs)
245 raise KeyError("No such diff key, available: %s" % self.diffs )
246 return getattr(self.result_column, key)
246 return getattr(self.result_column, key)
247
247
248 def __setitem__(self, key, value):
248 def __setitem__(self, key, value):
249 if key not in self.keys():
249 if key not in self.keys():
250 raise KeyError("No such diff key, available: %s" % self.diffs)
250 raise KeyError("No such diff key, available: %s" % self.diffs )
251 setattr(self.result_column, key, value)
251 setattr(self.result_column, key, value)
252
252
253 def __delitem__(self, key):
253 def __delitem__(self, key):
@@ -367,7 +367,7 b' class ColumnDelta(DictMixin, sqlalchemy.'
367 for_update=True))
367 for_update=True))
368 if toinit:
368 if toinit:
369 column._init_items(*toinit)
369 column._init_items(*toinit)
370
370
371 if not SQLA_06:
371 if not SQLA_06:
372 column.args = []
372 column.args = []
373
373
@@ -395,7 +395,6 b' class ColumnDelta(DictMixin, sqlalchemy.'
395 self._table = table
395 self._table = table
396 if not self.alter_metadata:
396 if not self.alter_metadata:
397 self._table.meta = sqlalchemy.MetaData(bind=self._table.bind)
397 self._table.meta = sqlalchemy.MetaData(bind=self._table.bind)
398
399 def _get_result_column(self):
398 def _get_result_column(self):
400 return getattr(self, '_result_column', None)
399 return getattr(self, '_result_column', None)
401
400
@@ -456,22 +455,18 b' class ChangesetTable(object):'
456
455
457 :param name: New name of the table.
456 :param name: New name of the table.
458 :type name: string
457 :type name: string
459 :param alter_metadata: If True, table will be removed from metadata
460 :type alter_metadata: bool
461 :param connection: reuse connection istead of creating new one.
458 :param connection: reuse connection istead of creating new one.
462 :type connection: :class:`sqlalchemy.engine.base.Connection` instance
459 :type connection: :class:`sqlalchemy.engine.base.Connection` instance
463 """
460 """
464 self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
465 engine = self.bind
461 engine = self.bind
466 self.new_name = name
462 self.new_name = name
467 visitorcallable = get_engine_visitor(engine, 'schemachanger')
463 visitorcallable = get_engine_visitor(engine, 'schemachanger')
468 run_single_visitor(engine, visitorcallable, self, connection, **kwargs)
464 run_single_visitor(engine, visitorcallable, self, connection, **kwargs)
469
465
470 # Fix metadata registration
466 # Fix metadata registration
471 if self.alter_metadata:
467 self.name = name
472 self.name = name
468 self.deregister()
473 self.deregister()
469 self._set_parent(self.metadata)
474 self._set_parent(self.metadata)
475
470
476 def _meta_key(self):
471 def _meta_key(self):
477 return sqlalchemy.schema._get_table_key(self.name, self.schema)
472 return sqlalchemy.schema._get_table_key(self.name, self.schema)
@@ -510,7 +505,6 b' class ChangesetColumn(object):'
510 `~migrate.changeset.constraint.UniqueConstraint` on this column.
505 `~migrate.changeset.constraint.UniqueConstraint` on this column.
511 :param primary_key_name: Creates :class:\
506 :param primary_key_name: Creates :class:\
512 `~migrate.changeset.constraint.PrimaryKeyConstraint` on this column.
507 `~migrate.changeset.constraint.PrimaryKeyConstraint` on this column.
513 :param alter_metadata: If True, column will be added to table object.
514 :param populate_default: If True, created column will be \
508 :param populate_default: If True, created column will be \
515 populated with defaults
509 populated with defaults
516 :param connection: reuse connection istead of creating new one.
510 :param connection: reuse connection istead of creating new one.
@@ -518,22 +512,19 b' populated with defaults'
518 :type index_name: string
512 :type index_name: string
519 :type unique_name: string
513 :type unique_name: string
520 :type primary_key_name: string
514 :type primary_key_name: string
521 :type alter_metadata: bool
522 :type populate_default: bool
515 :type populate_default: bool
523 :type connection: :class:`sqlalchemy.engine.base.Connection` instance
516 :type connection: :class:`sqlalchemy.engine.base.Connection` instance
524
517
525 :returns: self
518 :returns: self
526 """
519 """
527 self.populate_default = populate_default
520 self.populate_default = populate_default
528 self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
529 self.index_name = index_name
521 self.index_name = index_name
530 self.unique_name = unique_name
522 self.unique_name = unique_name
531 self.primary_key_name = primary_key_name
523 self.primary_key_name = primary_key_name
532 for cons in ('index_name', 'unique_name', 'primary_key_name'):
524 for cons in ('index_name', 'unique_name', 'primary_key_name'):
533 self._check_sanity_constraints(cons)
525 self._check_sanity_constraints(cons)
534
526
535 if self.alter_metadata:
527 self.add_to_table(table)
536 self.add_to_table(table)
537 engine = self.table.bind
528 engine = self.table.bind
538 visitorcallable = get_engine_visitor(engine, 'columngenerator')
529 visitorcallable = get_engine_visitor(engine, 'columngenerator')
539 engine._run_visitor(visitorcallable, self, connection, **kwargs)
530 engine._run_visitor(visitorcallable, self, connection, **kwargs)
@@ -550,59 +541,54 b' populated with defaults'
550
541
551 ``ALTER TABLE DROP COLUMN``, for most databases.
542 ``ALTER TABLE DROP COLUMN``, for most databases.
552
543
553 :param alter_metadata: If True, column will be removed from table object.
554 :type alter_metadata: bool
555 :param connection: reuse connection istead of creating new one.
544 :param connection: reuse connection istead of creating new one.
556 :type connection: :class:`sqlalchemy.engine.base.Connection` instance
545 :type connection: :class:`sqlalchemy.engine.base.Connection` instance
557 """
546 """
558 self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
559 if table is not None:
547 if table is not None:
560 self.table = table
548 self.table = table
561 engine = self.table.bind
549 engine = self.table.bind
562 if self.alter_metadata:
563 self.remove_from_table(self.table, unset_table=False)
564 visitorcallable = get_engine_visitor(engine, 'columndropper')
550 visitorcallable = get_engine_visitor(engine, 'columndropper')
565 engine._run_visitor(visitorcallable, self, connection, **kwargs)
551 engine._run_visitor(visitorcallable, self, connection, **kwargs)
566 if self.alter_metadata:
552 self.remove_from_table(self.table, unset_table=False)
567 self.table = None
553 self.table = None
568 return self
554 return self
569
555
570 def add_to_table(self, table):
556 def add_to_table(self, table):
571 if table is not None and self.table is None:
557 if table is not None and self.table is None:
572 self._set_parent(table)
558 self._set_parent(table)
573
559
574 def _col_name_in_constraint(self, cons, name):
560 def _col_name_in_constraint(self,cons,name):
575 return False
561 return False
576
562
577 def remove_from_table(self, table, unset_table=True):
563 def remove_from_table(self, table, unset_table=True):
578 # TODO: remove primary keys, constraints, etc
564 # TODO: remove primary keys, constraints, etc
579 if unset_table:
565 if unset_table:
580 self.table = None
566 self.table = None
581
567
582 to_drop = set()
568 to_drop = set()
583 for index in table.indexes:
569 for index in table.indexes:
584 columns = []
570 columns = []
585 for col in index.columns:
571 for col in index.columns:
586 if col.name != self.name:
572 if col.name!=self.name:
587 columns.append(col)
573 columns.append(col)
588 if columns:
574 if columns:
589 index.columns = columns
575 index.columns=columns
590 else:
576 else:
591 to_drop.add(index)
577 to_drop.add(index)
592 table.indexes = table.indexes - to_drop
578 table.indexes = table.indexes - to_drop
593
579
594 to_drop = set()
580 to_drop = set()
595 for cons in table.constraints:
581 for cons in table.constraints:
596 # TODO: deal with other types of constraint
582 # TODO: deal with other types of constraint
597 if isinstance(cons, (ForeignKeyConstraint,
583 if isinstance(cons,(ForeignKeyConstraint,
598 UniqueConstraint)):
584 UniqueConstraint)):
599 for col_name in cons.columns:
585 for col_name in cons.columns:
600 if not isinstance(col_name, basestring):
586 if not isinstance(col_name,basestring):
601 col_name = col_name.name
587 col_name = col_name.name
602 if self.name == col_name:
588 if self.name==col_name:
603 to_drop.add(cons)
589 to_drop.add(cons)
604 table.constraints = table.constraints - to_drop
590 table.constraints = table.constraints - to_drop
605
591
606 if table.c.contains_column(self):
592 if table.c.contains_column(self):
607 table.c.remove(self)
593 table.c.remove(self)
608
594
@@ -643,18 +629,14 b' class ChangesetIndex(object):'
643
629
644 :param name: New name of the Index.
630 :param name: New name of the Index.
645 :type name: string
631 :type name: string
646 :param alter_metadata: If True, Index object will be altered.
647 :type alter_metadata: bool
648 :param connection: reuse connection istead of creating new one.
632 :param connection: reuse connection istead of creating new one.
649 :type connection: :class:`sqlalchemy.engine.base.Connection` instance
633 :type connection: :class:`sqlalchemy.engine.base.Connection` instance
650 """
634 """
651 self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA)
652 engine = self.table.bind
635 engine = self.table.bind
653 self.new_name = name
636 self.new_name = name
654 visitorcallable = get_engine_visitor(engine, 'schemachanger')
637 visitorcallable = get_engine_visitor(engine, 'schemachanger')
655 engine._run_visitor(visitorcallable, self, connection, **kwargs)
638 engine._run_visitor(visitorcallable, self, connection, **kwargs)
656 if self.alter_metadata:
639 self.name = name
657 self.name = name
658
640
659
641
660 class ChangesetDefaultClause(object):
642 class ChangesetDefaultClause(object):
@@ -111,12 +111,12 b' class ModelGenerator(object):'
111 out.append(")")
111 out.append(")")
112 return out
112 return out
113
113
114 def _get_tables(self, missingA=False, missingB=False, modified=False):
114 def _get_tables(self,missingA=False,missingB=False,modified=False):
115 to_process = []
115 to_process = []
116 for bool_, names, metadata in (
116 for bool_,names,metadata in (
117 (missingA, self.diff.tables_missing_from_A, self.diff.metadataB),
117 (missingA,self.diff.tables_missing_from_A,self.diff.metadataB),
118 (missingB, self.diff.tables_missing_from_B, self.diff.metadataA),
118 (missingB,self.diff.tables_missing_from_B,self.diff.metadataA),
119 (modified, self.diff.tables_different, self.diff.metadataA),
119 (modified,self.diff.tables_different,self.diff.metadataA),
120 ):
120 ):
121 if bool_:
121 if bool_:
122 for name in names:
122 for name in names:
@@ -140,7 +140,7 b' class ModelGenerator(object):'
140 decls = ['from rhodecode.lib.dbmigrate.migrate.changeset import schema',
140 decls = ['from rhodecode.lib.dbmigrate.migrate.changeset import schema',
141 'meta = MetaData()']
141 'meta = MetaData()']
142 for table in self._get_tables(
142 for table in self._get_tables(
143 missingA=True, missingB=True, modified=True
143 missingA=True,missingB=True,modified=True
144 ):
144 ):
145 decls.extend(self.getTableDefn(table))
145 decls.extend(self.getTableDefn(table))
146
146
@@ -169,11 +169,11 b' class ModelGenerator(object):'
169 modelTable, col.name))
169 modelTable, col.name))
170 for modelCol, databaseCol, modelDecl, databaseDecl in diffDecl:
170 for modelCol, databaseCol, modelDecl, databaseDecl in diffDecl:
171 upgradeCommands.append(
171 upgradeCommands.append(
172 'assert False, "Can\'t alter columns: %s:%s=>%s"',
172 'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
173 modelTable, modelCol.name, databaseCol.name)
173 modelTable, modelCol.name, databaseCol.name))
174 downgradeCommands.append(
174 downgradeCommands.append(
175 'assert False, "Can\'t alter columns: %s:%s=>%s"',
175 'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
176 modelTable, modelCol.name, databaseCol.name)
176 modelTable, modelCol.name, databaseCol.name))
177 pre_command = ' meta.bind = migrate_engine'
177 pre_command = ' meta.bind = migrate_engine'
178
178
179 return (
179 return (
@@ -181,7 +181,7 b' class ModelGenerator(object):'
181 '\n'.join([pre_command] + ['%s%s' % (indent, line) for line in upgradeCommands]),
181 '\n'.join([pre_command] + ['%s%s' % (indent, line) for line in upgradeCommands]),
182 '\n'.join([pre_command] + ['%s%s' % (indent, line) for line in downgradeCommands]))
182 '\n'.join([pre_command] + ['%s%s' % (indent, line) for line in downgradeCommands]))
183
183
184 def _db_can_handle_this_change(self, td):
184 def _db_can_handle_this_change(self,td):
185 if (td.columns_missing_from_B
185 if (td.columns_missing_from_B
186 and not td.columns_missing_from_A
186 and not td.columns_missing_from_A
187 and not td.columns_different):
187 and not td.columns_different):
@@ -207,9 +207,9 b' class ModelGenerator(object):'
207 dbTable = self.diff.metadataB.tables[tableName]
207 dbTable = self.diff.metadataB.tables[tableName]
208
208
209 td = self.diff.tables_different[tableName]
209 td = self.diff.tables_different[tableName]
210
210
211 if self._db_can_handle_this_change(td):
211 if self._db_can_handle_this_change(td):
212
212
213 for col in td.columns_missing_from_B:
213 for col in td.columns_missing_from_B:
214 modelTable.columns[col].create()
214 modelTable.columns[col].create()
215 for col in td.columns_missing_from_A:
215 for col in td.columns_missing_from_A:
@@ -4,6 +4,7 b''
4 import shutil
4 import shutil
5 import warnings
5 import warnings
6 import logging
6 import logging
7 import inspect
7 from StringIO import StringIO
8 from StringIO import StringIO
8
9
9 from rhodecode.lib.dbmigrate import migrate
10 from rhodecode.lib.dbmigrate import migrate
@@ -49,7 +50,7 b' class PythonScript(base.BaseScript):'
49 :returns: Upgrade / Downgrade script
50 :returns: Upgrade / Downgrade script
50 :rtype: string
51 :rtype: string
51 """
52 """
52
53
53 if isinstance(repository, basestring):
54 if isinstance(repository, basestring):
54 # oh dear, an import cycle!
55 # oh dear, an import cycle!
55 from rhodecode.lib.dbmigrate.migrate.versioning.repository import Repository
56 from rhodecode.lib.dbmigrate.migrate.versioning.repository import Repository
@@ -65,7 +66,7 b' class PythonScript(base.BaseScript):'
65 excludeTables=[repository.version_table])
66 excludeTables=[repository.version_table])
66 # TODO: diff can be False (there is no difference?)
67 # TODO: diff can be False (there is no difference?)
67 decls, upgradeCommands, downgradeCommands = \
68 decls, upgradeCommands, downgradeCommands = \
68 genmodel.ModelGenerator(diff, engine).toUpgradeDowngradePython()
69 genmodel.ModelGenerator(diff,engine).toUpgradeDowngradePython()
69
70
70 # Store differences into file.
71 # Store differences into file.
71 src = Template(opts.pop('templates_path', None)).get_script(opts.pop('templates_theme', None))
72 src = Template(opts.pop('templates_path', None)).get_script(opts.pop('templates_theme', None))
@@ -136,12 +137,12 b' class PythonScript(base.BaseScript):'
136 funcname = base.operations[op]
137 funcname = base.operations[op]
137 script_func = self._func(funcname)
138 script_func = self._func(funcname)
138
139
139 try:
140 # check for old way of using engine
140 script_func(engine)
141 if not inspect.getargspec(script_func)[0]:
141 except TypeError:
142 raise TypeError("upgrade/downgrade functions must accept engine"
142 warnings.warn("upgrade/downgrade functions must accept engine"
143 " parameter (since version 0.5.4)")
143 " parameter (since version > 0.5.4)", MigrateDeprecationWarning)
144
144 raise
145 script_func(engine)
145
146
146 @property
147 @property
147 def module(self):
148 def module(self):
@@ -18,6 +18,7 b' class SqlScript(base.BaseScript):'
18
18
19 :returns: :class:`SqlScript instance <migrate.versioning.script.sql.SqlScript>`"""
19 :returns: :class:`SqlScript instance <migrate.versioning.script.sql.SqlScript>`"""
20 cls.require_notfound(path)
20 cls.require_notfound(path)
21
21 src = Template(opts.pop('templates_path', None)).get_sql_script(theme=opts.pop('templates_theme', None))
22 src = Template(opts.pop('templates_path', None)).get_sql_script(theme=opts.pop('templates_theme', None))
22 shutil.copy(src, path)
23 shutil.copy(src, path)
23 return cls(path)
24 return cls(path)
@@ -77,8 +77,7 b' def main(argv=None, **kwargs):'
77 %s
77 %s
78
78
79 Enter "%%prog help COMMAND" for information on a particular command.
79 Enter "%%prog help COMMAND" for information on a particular command.
80 """ % '\n\t'.join(["%s - %s" % (command.ljust(28),
80 """ % '\n\t'.join(["%s - %s" % (command.ljust(28), api.command_desc.get(command)) for command in commands])
81 api.command_desc.get(command)) for command in commands])
82
81
83 parser = PassiveOptionParser(usage=usage)
82 parser = PassiveOptionParser(usage=usage)
84 parser.add_option("-d", "--debug",
83 parser.add_option("-d", "--debug",
@@ -80,7 +80,7 b' class Template(pathed.Pathed):'
80 def get_repository(self, *a, **kw):
80 def get_repository(self, *a, **kw):
81 """Calls self._get_item('repository', *a, **kw)"""
81 """Calls self._get_item('repository', *a, **kw)"""
82 return self._get_item('repository', *a, **kw)
82 return self._get_item('repository', *a, **kw)
83
83
84 def get_script(self, *a, **kw):
84 def get_script(self, *a, **kw):
85 """Calls self._get_item('script', *a, **kw)"""
85 """Calls self._get_item('script', *a, **kw)"""
86 return self._get_item('script', *a, **kw)
86 return self._get_item('script', *a, **kw)
General Comments 0
You need to be logged in to leave comments. Login now