def test_all_traverse(self): writer = autogenerate.Rewriter() mocker = mock.Mock(side_effect=lambda context, revision, op: op) writer.rewrites(ops.MigrateOperation)(mocker) addcolop = ops.AddColumnOp('t1', sa.Column('x', sa.Integer())) directives = [ ops.MigrationScript( util.rev_id(), ops.UpgradeOps(ops=[ops.ModifyTableOps('t1', ops=[addcolop])]), ops.DowngradeOps(ops=[]), ) ] ctx, rev = mock.Mock(), mock.Mock() writer(ctx, rev, directives) eq_(mocker.mock_calls, [ mock.call(ctx, rev, directives[0]), mock.call(ctx, rev, directives[0].upgrade_ops), mock.call(ctx, rev, directives[0].upgrade_ops.ops[0]), mock.call(ctx, rev, addcolop), mock.call(ctx, rev, directives[0].downgrade_ops), ])
def _run_black_with_config(self, input_config, expected_additional_arguments_fn, cwd=None): self.cfg = _no_sql_testing_config(directives=input_config) impl = mock.Mock(attrs=("foo", "bar"), module_name="black_module") entrypoints = mock.Mock(return_value=iter([impl])) with mock.patch("pkg_resources.iter_entry_points", entrypoints), mock.patch( "alembic.script.write_hooks.subprocess" ) as mock_subprocess: rev = command.revision(self.cfg, message="x") eq_(entrypoints.mock_calls, [mock.call("console_scripts", "black")]) eq_( mock_subprocess.mock_calls, [ mock.call.run( [ sys.executable, "-c", "import black_module; black_module.foo.bar()", ] + expected_additional_arguments_fn(rev.path), cwd=cwd, ) ], )
def test_console_scripts(self): self.cfg = _no_sql_testing_config( directives=("\n[post_write_hooks]\n" "hooks=black\n" "black.type=console_scripts\n" "black.entrypoint=black\n" "black.options=-l 79\n")) impl = mock.Mock(attrs=("foo", "bar"), module_name="black_module") entrypoints = mock.Mock(return_value=iter([impl])) with mock.patch("pkg_resources.iter_entry_points", entrypoints), mock.patch( "alembic.script.write_hooks.subprocess" ) as mock_subprocess: rev = command.revision(self.cfg, message="x") eq_(entrypoints.mock_calls, [mock.call("console_scripts", "black")]) eq_( mock_subprocess.mock_calls, [ mock.call.run([ sys.executable, "-c", "import black_module; black_module.foo.bar()", rev.path, "-l", "79", ]) ], )
def test_chained_ops(self): writer1 = autogenerate.Rewriter() writer2 = autogenerate.Rewriter() @writer1.rewrites(ops.AddColumnOp) def add_column_nullable(context, revision, op): if op.column.nullable: return op else: op.column.nullable = True return [ op, ops.AlterColumnOp( op.table_name, op.column.name, modify_nullable=False, existing_type=op.column.type, ), ] @writer2.rewrites(ops.AddColumnOp) def add_column_idx(context, revision, op): idx_op = ops.CreateIndexOp("ixt", op.table_name, [op.column.name]) return [op, idx_op] directives = [ ops.MigrationScript( util.rev_id(), ops.UpgradeOps(ops=[ ops.ModifyTableOps( "t1", ops=[ ops.AddColumnOp( "t1", sa.Column("x", sa.Integer(), nullable=False), ) ], ) ]), ops.DowngradeOps(ops=[]), ) ] ctx, rev = mock.Mock(), mock.Mock() writer1.chain(writer2)(ctx, rev, directives) eq_( autogenerate.render_python_code(directives[0].upgrade_ops), "# ### commands auto generated by Alembic - please adjust! ###\n" " op.add_column('t1', " "sa.Column('x', sa.Integer(), nullable=True))\n" " op.create_index('ixt', 't1', ['x'], unique=False)\n" " op.alter_column('t1', 'x',\n" " existing_type=sa.Integer(),\n" " nullable=False)\n" " # ### end Alembic commands ###", )
def test_no_needless_pass(self): writer1 = autogenerate.Rewriter() @writer1.rewrites(ops.AlterColumnOp) def rewrite_alter_column(context, revision, op): return [] directives = [ ops.MigrationScript( util.rev_id(), ops.UpgradeOps( ops=[ ops.ModifyTableOps( "t1", ops=[ ops.AlterColumnOp( "foo", "bar", modify_nullable=False, existing_type=sa.Integer(), ), ops.AlterColumnOp( "foo", "bar", modify_nullable=False, existing_type=sa.Integer(), ), ], ), ops.ModifyTableOps( "t1", ops=[ ops.AlterColumnOp( "foo", "bar", modify_nullable=False, existing_type=sa.Integer(), ) ], ), ] ), ops.DowngradeOps(ops=[]), ) ] ctx, rev = mock.Mock(), mock.Mock() writer1(ctx, rev, directives) eq_( autogenerate.render_python_code(directives[0].upgrade_ops), "# ### commands auto generated by Alembic - please adjust! ###\n" " pass\n" " # ### end Alembic commands ###", )
def _test_tz(self, timezone_arg, given, expected): script = ScriptDirectory(_get_staging_directory(), file_template="%(rev)s_%(slug)s_" "%(year)s_%(month)s_" "%(day)s_%(hour)s_" "%(minute)s_%(second)s", timezone=timezone_arg) with mock.patch( "alembic.script.base.datetime", mock.Mock(datetime=mock.Mock(utcnow=lambda: given, now=lambda: given))): create_date = script._generate_create_date() eq_(create_date, expected)
def test_double_migrate_table(self): writer = autogenerate.Rewriter() idx_ops = [] @writer.rewrites(ops.ModifyTableOps) def second_table(context, revision, op): return [ op, ops.ModifyTableOps('t2', ops=[ ops.AddColumnOp('t2', sa.Column('x', sa.Integer())) ]) ] @writer.rewrites(ops.AddColumnOp) def add_column(context, revision, op): idx_op = ops.CreateIndexOp('ixt', op.table_name, [op.column.name]) idx_ops.append(idx_op) return [ op, idx_op ] directives = [ ops.MigrationScript( util.rev_id(), ops.UpgradeOps(ops=[ ops.ModifyTableOps('t1', ops=[ ops.AddColumnOp('t1', sa.Column('x', sa.Integer())) ]) ]), ops.DowngradeOps(ops=[]), ) ] ctx, rev = mock.Mock(), mock.Mock() writer(ctx, rev, directives) eq_( [d.table_name for d in directives[0].upgrade_ops.ops], ['t1', 't2'] ) is_( directives[0].upgrade_ops.ops[0].ops[1], idx_ops[0] ) is_( directives[0].upgrade_ops.ops[1].ops[1], idx_ops[1] )
def test_uses_custom_compare_type_function(self): my_compare_type = mock.Mock() self.context._user_compare_type = my_compare_type uo = ops.UpgradeOps(ops=[]) ctx = self.autogen_context autogenerate._produce_net_changes(ctx, uo) first_table = self.m2.tables["sometable"] first_column = first_table.columns["id"] eq_(len(my_compare_type.mock_calls), 2) # We'll just test the first call _, args, _ = my_compare_type.mock_calls[0] ( context, inspected_column, metadata_column, inspected_type, metadata_type, ) = args eq_(context, self.context) eq_(metadata_column, first_column) eq_(metadata_type, first_column.type) eq_(inspected_column.name, first_column.name) eq_(type(inspected_type), INTEGER)
def test_steps(self): import alembic alembic.mock_event_listener = None self._env_file_fixture() with mock.patch('alembic.mock_event_listener', mock.Mock()) as mymock: super(CallbackEnvironmentTest, self).test_steps() calls = mymock.call_args_list assert calls for call in calls: args, kw = call assert not args assert set(kw.keys()) >= self.exp_kwargs assert kw['run_args'] == {} assert hasattr(kw['ctx'], 'get_current_revision') step = kw['step'] assert isinstance(step.is_upgrade, bool) assert isinstance(step.is_stamp, bool) assert isinstance(step.is_migration, bool) assert isinstance(step.up_revision_id, compat.string_types) assert isinstance(step.up_revision, Script) for revtype in 'up', 'down', 'source', 'destination': revs = getattr(step, '%s_revisions' % revtype) assert isinstance(revs, tuple) for rev in revs: assert isinstance(rev, Script) revids = getattr(step, '%s_revision_ids' % revtype) for revid in revids: assert isinstance(revid, compat.string_types) heads = kw['heads'] assert hasattr(heads, '__iter__') for h in heads: assert h is None or isinstance(h, compat.string_types)
def _run_black_with_config(self, input_config, expected_additional_arguments_fn, cwd=None): self.cfg = _no_sql_testing_config(directives=input_config) class MocksCantName: name = "black" attr = "bar" module = "black_module.foo" importlib_metadata_get = mock.Mock(return_value=iter([MocksCantName])) with mock.patch( "alembic.util.compat.importlib_metadata_get", importlib_metadata_get, ), mock.patch( "alembic.script.write_hooks.subprocess") as mock_subprocess: rev = command.revision(self.cfg, message="x") eq_(importlib_metadata_get.mock_calls, [mock.call("console_scripts")]) eq_( mock_subprocess.mock_calls, [ mock.call.run( [ sys.executable, "-c", "import black_module.foo; black_module.foo.bar()", ] + expected_additional_arguments_fn(rev.path), cwd=cwd, ) ], )
def test_upgrade(self): head = HeadMaintainer(mock.Mock(), [self.a.revision]) """ upgrade a -> b2, b2 upgrade a -> b3, b3 upgrade b2, b3 -> c2, c2 upgrade c2 -> d2, d2 upgrade a -> b1, b1 upgrade b1, b2 -> c1, c1 upgrade c1 -> d1, d1 """ steps = [ (self.up_(self.b2), ('b2', )), (self.up_(self.b3), ( 'b2', 'b3', )), (self.up_(self.c2), ('c2', )), (self.up_(self.d2), ('d2', )), (self.up_(self.b1), ( 'b1', 'd2', )), (self.up_(self.c1), ('c1', 'd2')), (self.up_(self.d1), ('d1', 'd2')), ] for step, assert_ in steps: head.update_to_step(step) eq_(head.heads, set(assert_))
def test_downgrade_branch_dependency(self): """c2branch depends on c1branch so taking down c1branch requires taking down both""" destination = "c1branch@{}".format(self.b.revision) source = self.d1.revision, self.d2.revision revs = self.env._downgrade_revs(destination, source) # Drops c1, d1 as requested, also drops d2 due to dependence on d1. # Full ordering of migrations is not consistent so verify partial # ordering only. rev_ids = [rev.revision.revision for rev in revs] assert set(rev_ids) == { self.c1.revision, self.d1.revision, self.d2.revision, } assert rev_ids.index(self.d1.revision) < rev_ids.index( self.c1.revision) assert rev_ids.index(self.d2.revision) < rev_ids.index( self.c1.revision) # Verify final state. heads = set(util.to_tuple(source, default=())) head = HeadMaintainer(mock.Mock(), heads) for rev in revs: head.update_to_step(rev) eq_(head.heads, set([self.c2.revision]))
def test_script_location(self): config = _no_sql_testing_config() script = ScriptDirectory.from_config(config) def normpath(path): return path.replace("/", ":NORM:") normpath = mock.Mock(side_effect=normpath) with mock.patch("os.path.normpath", normpath): eq_( script._version_locations, ( os.path.abspath( os.path.join( _get_staging_directory(), "scripts", "versions" ) ).replace("/", ":NORM:"), ), ) eq_( script.versions, os.path.abspath( os.path.join( _get_staging_directory(), "scripts", "versions" ) ).replace("/", ":NORM:"), )
def test_invoke(self): my_formatter = mock.Mock() write_hooks.register("my_writer")(my_formatter) write_hooks._invoke("my_writer", "/some/path", {"option": 1}) my_formatter.assert_called_once_with("/some/path", {"option": 1})
def test_run_cmd_args_missing(self): canary = mock.Mock() orig_revision = command.revision # the command function has "process_revision_directives" # however the ArgumentParser does not. ensure things work def revision( config, message=None, autogenerate=False, sql=False, head="head", splice=False, branch_label=None, version_path=None, rev_id=None, depends_on=None, process_revision_directives=None, ): canary(config, message=message) revision.__module__ = "alembic.command" # CommandLine() pulls the function into the ArgumentParser # and needs the full signature, so we can't patch the "revision" # command normally as ArgumentParser gives us no way to get to it. config.command.revision = revision try: commandline = config.CommandLine() options = commandline.parser.parse_args(["revision", "-m", "foo"]) commandline.run_cmd(self.cfg, options) finally: config.command.revision = orig_revision eq_(canary.mock_calls, [mock.call(self.cfg, message="foo")])
def test_script_location_muliple(self): config = _multi_dir_testing_config() script = ScriptDirectory.from_config(config) def normpath(path): return path.replace("/", ":NORM:") normpath = mock.Mock(side_effect=normpath) with mock.patch("os.path.normpath", normpath): eq_( script._version_locations, [ os.path.abspath( os.path.join(_get_staging_directory(), "model1/")).replace("/", ":NORM:"), os.path.abspath( os.path.join(_get_staging_directory(), "model2/")).replace("/", ":NORM:"), os.path.abspath( os.path.join(_get_staging_directory(), "model3/")).replace("/", ":NORM:"), ], )
def test_ascii_unicode(self): stdout = mock.Mock(encoding=None) cfg = config.Config(stdout=stdout) cfg.print_stdout(compat.u("méil %s %s"), "x", "y") eq_( stdout.mock_calls, [mock.call.write("m?il x y"), mock.call.write("\n")], )
def test_utf8_unicode(self): stdout = mock.Mock(encoding="latin-1") cfg = config.Config(stdout=stdout) cfg.print_stdout(compat.u("méil %s %s"), "x", "y") eq_( stdout.mock_calls, [mock.call.write(compat.u("méil x y")), mock.call.write("\n")], )
def test_only_formats_output_with_args(self): stdout = mock.Mock(encoding=None) cfg = config.Config(stdout=stdout) cfg.print_stdout(compat.u("test 3%")) eq_( stdout.mock_calls, [mock.call.write("test 3%"), mock.call.write("\n")], )
def test_plain(self): stdout = mock.Mock(encoding="latin-1") cfg = config.Config(stdout=stdout) cfg.print_stdout("test %s %s", "x", "y") eq_( stdout.mock_calls, [mock.call.write("test x y"), mock.call.write("\n")], )
def _assert_upgrade(self, destination, source, expected, expected_heads): revs = self.env._upgrade_revs(destination, source) eq_(revs, expected) heads = set(util.to_tuple(source, default=())) head = HeadMaintainer(mock.Mock(), heads) for rev in revs: head.update_to_step(rev) eq_(head.heads, expected_heads)
def _fixture(self): migration_context = mock.Mock(opts={}) op = Operations(migration_context) batch = op.batch_alter_table('tname', recreate='never').__enter__() with mock.patch("alembic.operations.sa_schema") as mock_schema: yield batch batch.impl.flush() self.mock_schema = mock_schema
def test_generic(self): hook1 = mock.Mock() hook2 = mock.Mock() write_hooks.register("hook1")(hook1) write_hooks.register("hook2")(hook2) self.cfg = _no_sql_testing_config(directives=("\n[post_write_hooks]\n" "hooks=hook1,hook2\n" "hook1.type=hook1\n" "hook1.arg1=foo\n" "hook2.type=hook2\n" "hook2.arg1=bar\n")) rev = command.revision(self.cfg, message="x") eq_( hook1.mock_calls, [ mock.call( rev.path, { "type": "hook1", "arg1": "foo", "_hook_name": "hook1" }, ) ], ) eq_( hook2.mock_calls, [ mock.call( rev.path, { "type": "hook2", "arg1": "bar", "_hook_name": "hook2" }, ) ], )
def test_column_type_not_modified_custom_compare_type_returns_False(self): my_compare_type = mock.Mock() my_compare_type.return_value = False self.context._user_compare_type = my_compare_type diffs = [] ctx = self.autogen_context diffs = [] autogenerate._produce_net_changes(ctx, diffs) eq_(diffs, [])
def test_column_type_modified_custom_compare_type_returns_True(self): my_compare_type = mock.Mock() my_compare_type.return_value = True self.context._user_compare_type = my_compare_type ctx = self.autogen_context uo = ops.UpgradeOps(ops=[]) autogenerate._produce_net_changes(ctx, uo) diffs = uo.as_diffs() eq_(diffs[0][0][0], "modify_type") eq_(diffs[1][0][0], "modify_type")
def _fixture(self, schema=None): migration_context = mock.Mock( opts={}, impl=mock.MagicMock(__dialect__='sqlite')) op = Operations(migration_context) batch = op.batch_alter_table('tname', recreate='never', schema=schema).__enter__() mock_schema = mock.MagicMock() with mock.patch("alembic.operations.schemaobj.sa_schema", mock_schema): yield batch batch.impl.flush() self.mock_schema = mock_schema
def test_stamp_api_creates_table(self): context = self.make_one(connection=self.connection) assert ('alembic_version' not in Inspector(self.connection).get_table_names()) script = mock.Mock( _stamp_revs=lambda revision, heads: [_up(None, 'a', True), _up(None, 'b', True)]) context.stamp(script, 'b') eq_(context.get_current_heads(), ('a', 'b')) assert ('alembic_version' in Inspector(self.connection).get_table_names())
def test_stamp_api_creates_table(self): context = self.make_one(connection=self.connection) assert ("alembic_version" not in inspect(self.connection).get_table_names()) script = mock.Mock(_stamp_revs=lambda revision, heads: [ _up(None, "a", True), _up(None, "b", True), ]) context.stamp(script, "b") eq_(context.get_current_heads(), ("a", "b")) assert "alembic_version" in inspect(self.connection).get_table_names()
def test_upgrade(self): head = HeadMaintainer(mock.Mock(), [self.a.revision]) steps = [ (self.up_(self.b3), ('b3',)), (self.up_(self.b1), ('b1', 'b3',)), (self.up_(self.b2), ('b1', 'b2', 'b3',)), (self.up_(self.c2), ('c2',)), (self.up_(self.d2), ('d2',)), (self.up_(self.c1), ('c1', 'd2')), (self.up_(self.d1), ('d1', 'd2')), ] for step, assert_ in steps: head.update_to_step(step) eq_(head.heads, set(assert_))
def test_upgrade(self): head = HeadMaintainer(mock.Mock(), [self.a.revision]) steps = [ (self.up_(self.b3), ("b3", )), (self.up_(self.b1), ("b1", "b3")), (self.up_(self.b2), ("b1", "b2", "b3")), (self.up_(self.c2), ("c2", )), (self.up_(self.d2), ("d2", )), (self.up_(self.c1), ("c1", "d2")), (self.up_(self.d1), ("d1", "d2")), ] for step, assert_ in steps: head.update_to_step(step) eq_(head.heads, set(assert_))